[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Set the default behavior, in case people don't have core.autocrlf set.\n* text=auto\n\n# Declare text files that will always have LF line endings on checking\noni eol=lf\n\n# Ignore the yarn library from Linguist, for the Github Language Stats.\nlib/yarn/* linguist-vendored=true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!-- Want this issue prioritized? Please consider supporting the project and becoming an insider!\n👉  https://www.onivim.io/Insiders -->\n\n**Oni Version:**\n**Neovim Version (Linux only):**\n**Operating System:**\n\n**Issue:**\n\n**Expected behavior:**\n\n**Actual behavior:**\n\n**Steps to reproduce:**\n"
  },
  {
    "path": ".github/config.yml",
    "content": "# Comment to be posted to on first time issues\nnewIssueWelcomeComment: >\n  Hello and welcome to the Oni repository! Thanks for opening your first issue here. To help us out, please make sure to include as much detail as possible - including screenshots and logs, if possible.\nbackers:\n- 78856\n- 1359421\n- 4650931\n- 13532591\n- 5097613\n- 22454918\n- 347552\n- 977348\n- 28748\n- 2835826\n- 515720\n- 124171\n- 230476\n- 10102132\n- 10038688\n- 817509\n- 163128\n- 4762\n- 933251\n- 3974037\n- 141159\n- 10263\n- 3117205\n- 5697723\n- 6803419\n- 1718128\n- 2042893\n- 14060883\n- 244396\n- 8832878\n- 5127194\n- 1764368\n- 468548\n- 2318955\n- 28788713\n- 1491574\n- 6972449\n- 20133970\n- 5804765\n- 360703\n- 120710\n- 4607311\n- 7727602\n- 9206426\n- 119977\n- 14045559\n- 284789\n- 2899448\n- 2766423\n"
  },
  {
    "path": ".gitignore",
    "content": "# Yarn\nyarn.lock\n\n.DS_Store\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Python\n.mypy_cache\n\n# Local app data\n$LOCALAPPDATA\n\n# Output\nlib\nlib_test\ndist\ns3_dist\n\n### https://raw.github.com/github/gitignore/2b3b1f428fb84dc4ba3ad2307ec44af3c5799848/Node.gitignore\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\nbuild/*.ico\n\n# Dependency directories\nnode_modules\njspm_packages\n\n# Optional npm cache directory\n.npm\n\n# npm package-lock files\npackage-lock.json\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n\n\n### https://raw.github.com/github/gitignore/2b3b1f428fb84dc4ba3ad2307ec44af3c5799848/Global/Linux.gitignore\n\n*~\n\n# temporary files which can be created if a process still has a handle open of a deleted file\n.fuse_hidden*\n\n# KDE directory preferences\n.directory\n\n# Linux trash folder which might appear on any partition or disk\n.Trash-*\n\n# .nfs files are created when an open file is removed but is still being accessed\n.nfs*\n\n\n### https://raw.github.com/github/gitignore/2b3b1f428fb84dc4ba3ad2307ec44af3c5799848/Global/macOS.gitignore\n\n*.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n\n### https://raw.github.com/github/gitignore/2b3b1f428fb84dc4ba3ad2307ec44af3c5799848/Global/Windows.gitignore\n\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n# OCaml / Reason\n.merlin\n\nyarn.lock\n\n# Webpack stats file\nstats.json\n\n# User Notes\n.notes\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"vim/default/bundle/targets.vim\"]\n\tpath = vim/default/bundle/targets.vim\n\turl = https://github.com/wellle/targets.vim\n[submodule \"vim/default/bundle/vim-commentary\"]\n\tpath = vim/default/bundle/vim-commentary\n\turl = https://github.com/tpope/vim-commentary\n[submodule \"vim/default/bundle/vim-unimpaired\"]\n\tpath = vim/default/bundle/vim-unimpaired\n\turl = https://github.com/tpope/vim-unimpaired\n[submodule \"vim/default/bundle/vim-surround\"]\n\tpath = vim/default/bundle/vim-surround\n\turl = https://github.com/tpope/vim-surround.git\n[submodule \"vim/core/typescript-vim\"]\n\tpath = vim/core/typescript-vim\n\turl = https://github.com/leafgarland/typescript-vim\n"
  },
  {
    "path": ".npmignore",
    "content": "# Empty .npmignore to allow for including .gitignore'd built files\n"
  },
  {
    "path": ".nvmrc",
    "content": "9\n"
  },
  {
    "path": ".oni/config.js",
    "content": "// For more information on customizing Oni,\n// check out our wiki page:\n// https://github.com/onivim/oni/wiki/Configuration\n\nconst activate = oni => {\n    console.log(\"Oni config activated\")\n}\n\nconst deactivate = () => {\n    console.log(\"Oni config deactivated\")\n}\n\nmodule.exports = {\n    activate,\n    deactivate,\n    \"workspace.testFileMappings\": [\n        {\n            sourceFolder: \"browser/src\",\n            mappedFolder: \"browser/test\",\n            mappedFileName: \"${fileName}Tests.ts\",\n            templateFilePath: \".oni/templates/UnitTestTemplate.ts.template\",\n        },\n    ],\n}\n"
  },
  {
    "path": ".oni/templates/UnitTestTemplate.ts.template",
    "content": "/**\n * ${TM_FILENAME_BASE}.ts\n */\n\nimport * as assert from \"assert\"\n\ndescribe(\"${TM_FILENAME_BASE}\", () => {\n    it(\"${1:tests}\", async () => {\n        ${2:assert.ok(false, \"fail\")}\n        ${0}\n    })\n})\n\n"
  },
  {
    "path": ".prettierignore",
    "content": "package.json\nvim/core/oni-plugin-typescript/package.json\nlib/yarn/*\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 100,\n  \"semi\": false,\n  \"singleQuote\": false,\n  \"tabWidth\": 4,\n  \"trailingComma\": \"all\"\n}\n"
  },
  {
    "path": ".travis.yml",
    "content": "sudo: required\ndist: trusty\nlanguage: node_js\n\nbranches:\n  only:\n  - master\n  - /^release.*/\n\ncache:\n  directories:\n  - .oni_build_cache\n\nmatrix:\n  include:\n  - os: linux\n    sudo: required\n    dist: trusty\n    node_js: 8\n  - os: osx # OSX 10.12\n    node_js: 8\n  - os: osx # OSX 10.11\n    node_js: 8\n    osx_image: xcode8\n  allow_failures:\n    - osx_image: xcode8\n\naddons:\n  apt:\n    packages:\n    - libxkbfile-dev\n    - libgnome-keyring-dev\n    - icnsutils\n    - graphicsmagick\n    - xz-utils\n    - rpm\n    - bsdtar\n\nbefore_install:\n- |\n    # Get the files modified in this commit, and check there is\n    # actual code changes made. If there isn't, stop the build.\n    MODIFIED_FILES=$(git diff --name-only $TRAVIS_COMMIT_RANGE)\n\n    if ! echo ${MODIFIED_FILES} | grep -qvE '(\\.md$)/'; then\n      echo \"Only documents were updated, stopping...\"\n      exit\n    fi\n\n\ninstall:\n- npm install -g yarn@1.9.4\n# Remove problematic version of yarn\n- rm -rf ~/.yarn/bin\n- yarn --version\n- which yarn\n- yarn install\n\nscript:\n- npm run check-cached-binaries\n- ./build/script/install-reason.sh\n- ./build/script/travis-build.sh\n- travis_wait ./build/script/travis-pack.sh\n- ./build/script/travis-test.sh\n\ndeploy:\n    - provider: s3\n      access_key_id: AKIAIYMATI2CEFTHPBOQ\n      secret_access_key:\n        secure: S4f/aczEABGAMKk2tmVSkoGx+T2TLPmz5z6x6RKaM+eDmAaVSAELlIj1eAz6Tu2lv3jz+cpyAIISZNC/phORsJWwzbSZHVycLrMG0N3fDTqKFxu1fl6L3b3exRe9SiKXug73ZvHfktzd/XfRcgZKop4qgrwGiM57m0ZuZb/j1LkgjytTuvNAUxXbA84I8LZs/NhY17XuXq+KPlGElIHy3UFoGqQ8pBnTypkIU5rQTsoeAxXLBE8JAFfz+nBGZ7dx6OMbQcKX5jKh/gR3vk+4aTgV8gNE2Zp24ErjSqF2zly/gP9nE2DpfR7jqpZVHnb/v+OEjRDS80tLhPo8Dbibzwt2ZZNADpYBjSGtphwAmq4DCvJ7ORExOB5+O3wmXKQGdItyBTS7sW44n6BTyv87WxWuCaSDQ9QaO9PrbJdN5YGEYeRxSTM7Mn0t72IILkfFCUeSg6fl6tFs9iWIj5zltbxH1GQsRpA8j1Idg4O+894KnQABtw/YKh6rrdeYS9y/100qAjtV6qYyiP2IdPqMWGuasOiz87q3CQ8Ejd7uhiTjAaINVqos+0k04Yf5+rT4MqkeXnYFzjXuXcqDlpq6yJIZv3aD+PMSlZi2WmTYnPJXQFndHo/x9FhEh90UF9WdO5S27ySRSo8XQT4DyL3ToPkqz8y0slNmaNqiqMouQAU=\n      bucket: oni-media\n      local-dir: dist/media\n      acl: public_read\n      region: us-west-2\n      skip_cleanup: true\n      on:\n        condition: $TRAVIS_OS_NAME = osx\n        repo: onivim/oni\n    - provider: releases\n      api_key:\n        secure: qB2KX7c9gRf9HDNetUVJOSa1Lo81QJiukOChOEzGUkYzD/et/2uNgzl0AQX0jB6aOYNwtZAxTd/ON3TTbEWh90o+R1PmQUgQCZ8xIFjOwnQmuHFp4hHoOWNI/ahmQ3W5UD+gmkV5YTRDMfuNnRjraDcQ5R6744Gii4zHGBwnJQsKVh65rxChHfkAJ1WEoX0lUbEM9Veyof4W+xLEgf45eDNvG3fz2y11D2qcvJNckVdvaYIWFwVrefcmofnQvLoWhs8gs6tLBKxaieZ4DcKH+Q5ux+t2VT8LYOR6gkCzuBgUbGUB+AlfCrNR2T7H3LLONIbUMB8/3sF0+oojj9tXPoagHzmwL2gnE7esLxIXc90LbAMpzLwMDvOgA8YEIsgKKtM92BqMK3Pv2clDv+Wmu8Al/QOU8v4Zj5dF09pqa8VM95xPx8t5Harrz+AN6HhZtzoqceooCBtJaGDb5jRdIjWtg4LkJN82mMuNAcbTLUotWp9UxJyqiS+WLrF4cIjPBoq9AAay8XnqLJHpjLGq2Mfp8i9qRFJPr7m2a1WozUUL5/s8Fb7oVOm6rYodXP3ZrdF+0OFMMKoaMfxOg2IhKRIk+S6XYp64i8J4lOFJ0W0dg0ap+f3PsWTYaA7YQ+/SMSv0zsZdrprT80i/Mx5F5HjiljX6GDmanZCdEG1b2a8=\n      file_glob: true\n      file:\n        - dist/*.dmg\n        - dist/*.zip\n      skip_cleanup: true\n      on:\n        condition: $TRAVIS_OS_NAME = osx\n        tags: true\n        repo: onivim/oni\n    - provider: releases\n      api_key:\n        secure: qB2KX7c9gRf9HDNetUVJOSa1Lo81QJiukOChOEzGUkYzD/et/2uNgzl0AQX0jB6aOYNwtZAxTd/ON3TTbEWh90o+R1PmQUgQCZ8xIFjOwnQmuHFp4hHoOWNI/ahmQ3W5UD+gmkV5YTRDMfuNnRjraDcQ5R6744Gii4zHGBwnJQsKVh65rxChHfkAJ1WEoX0lUbEM9Veyof4W+xLEgf45eDNvG3fz2y11D2qcvJNckVdvaYIWFwVrefcmofnQvLoWhs8gs6tLBKxaieZ4DcKH+Q5ux+t2VT8LYOR6gkCzuBgUbGUB+AlfCrNR2T7H3LLONIbUMB8/3sF0+oojj9tXPoagHzmwL2gnE7esLxIXc90LbAMpzLwMDvOgA8YEIsgKKtM92BqMK3Pv2clDv+Wmu8Al/QOU8v4Zj5dF09pqa8VM95xPx8t5Harrz+AN6HhZtzoqceooCBtJaGDb5jRdIjWtg4LkJN82mMuNAcbTLUotWp9UxJyqiS+WLrF4cIjPBoq9AAay8XnqLJHpjLGq2Mfp8i9qRFJPr7m2a1WozUUL5/s8Fb7oVOm6rYodXP3ZrdF+0OFMMKoaMfxOg2IhKRIk+S6XYp64i8J4lOFJ0W0dg0ap+f3PsWTYaA7YQ+/SMSv0zsZdrprT80i/Mx5F5HjiljX6GDmanZCdEG1b2a8=\n      file_glob: true\n      file:\n          - dist/*.deb\n          - dist/*.rpm\n          - dist/*.tar.gz\n      skip_cleanup: true\n      on:\n        condition: $TRAVIS_OS_NAME = linux\n        tags: true\n        repo: onivim/oni\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            // Debug files that configure Electron (main.js, Menu.js, etc.)\n            \"name\": \"Oni Main Process\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"cwd\": \"${workspaceRoot}\",\n            \"program\": \"${workspaceRoot}/lib/main/src/main.js\",\n            \"runtimeExecutable\": \"${workspaceRoot}/node_modules/.bin/electron\",\n            \"windows\": {\n                \"runtimeExecutable\": \"${workspaceRoot}/node_modules/.bin/electron.cmd\"\n            },\n            \"runtimeArgs\": [\"--enable-logging\"],\n            \"console\": \"internalConsole\"\n        },\n        {\n            // Debug typescript files\n            // (must run `npm run build-debug` first to generate bundle.js.map)\n            \"name\": \"Oni Application\",\n            \"type\": \"chrome\", // <-- requires Extension \"Debugger for Chrome\"\n            \"request\": \"launch\",\n            \"runtimeExecutable\": \"${workspaceRoot}/node_modules/.bin/electron\",\n            \"windows\": {\n                \"runtimeExecutable\": \"${workspaceRoot}/node_modules/.bin/electron.cmd\"\n            },\n            \"runtimeArgs\": [\"--enable-logging\", \"${workspaceRoot}/lib/main/src/main.js\"],\n            \"webRoot\": \"${workspaceRoot}\",\n            \"sourceMaps\": true,\n            \"sourceMapPathOverrides\": {\n                \"webpack:///./*\": \"${webRoot}/*\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": ".yarnrc",
    "content": "--add.ignore-engines true\n"
  },
  {
    "path": "@types/color-normalize/index.d.ts",
    "content": "type ColorInput =\n    | string\n    | Int8Array\n    | Int16Array\n    | Int32Array\n    | Uint8Array\n    | Uint16Array\n    | Uint32Array\n    | Float32Array\n    | Float64Array\n    | Array\n    | Uint8ClampedArray\n\ndeclare function colorNormalize(color: ColorInput, type: \"float\"): float[]\ndeclare function colorNormalize(color: ColorInput, type: \"array\"): float[]\ndeclare function colorNormalize(color: ColorInput, type: \"int8\"): Int8Array\ndeclare function colorNormalize(color: ColorInput, type: \"int16\"): Int8Array\ndeclare function colorNormalize(color: ColorInput, type: \"int32\"): Int8Array\ndeclare function colorNormalize(color: ColorInput, type: \"uint\"): Uint8Array\ndeclare function colorNormalize(color: ColorInput, type: \"uint8\"): Uint8Array\ndeclare function colorNormalize(color: ColorInput, type: \"uint16\"): Uint8Array\ndeclare function colorNormalize(color: ColorInput, type: \"uint32\"): Uint8Array\ndeclare function colorNormalize(color: ColorInput, type: \"float32\"): Float32Array\ndeclare function colorNormalize(color: ColorInput, type: \"float64\"): Float64Array\ndeclare function colorNormalize(color: ColorInput, type: \"uint_clamped\"): Uint8ClampedArray\ndeclare function colorNormalize(color: ColorInput, type: \"uint8_clamped\"): Uint8ClampedArray\ndeclare function colorNormalize(color: ColorInput): float[]\n\ndeclare module \"color-normalize\" {\n    export default colorNormalize\n}\n"
  },
  {
    "path": "@types/font-manager/index.d.ts",
    "content": "type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900\ntype FontWidth = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\n\ninterface QueryFontDescriptor {\n    postscriptName?: string\n    family?: string\n    style?: string\n    weight?: FontWeight\n    width?: FontWidth\n    italic?: boolean\n    monospace?: boolean\n}\n\ninterface ResultFontDescriptor {\n    path: string\n    postscriptName: string\n    family: string\n    style: string\n    weight: FontWeight\n    width: FontWidth\n    italic: boolean\n    monospace: boolean\n}\n\ninterface FontManager {\n    getAvailableFonts: (callback: (availableFonts: ResultFontDescriptor[]) => void) => void\n    getAvailableFontsSync: () => ResultFontDescriptor[]\n\n    findFonts: (\n        fontDescriptor: QueryFontDescriptor,\n        callback: (foundFonts: ResultFontDescriptor[]) => void,\n    ) => void\n    findFontsSync: (fontDescriptor: QueryFontDescriptor) => ResultFontDescriptor[]\n\n    findFont: (\n        fontDescriptor: QueryFontDescriptor,\n        callback: (foundFont: ResultFontDescriptor | null) => void,\n    ) => void\n    findFontSync: (fontDescriptor: QueryFontDescriptor) => ResultFontDescriptor | null\n\n    substituteFont: (\n        postscriptName: string,\n        text: string,\n        callback: (replacement: ResultFontDescriptor[]) => void,\n    ) => void\n    substituteFontSync: (postscriptName: string, text: string) => ResultFontDescriptor[]\n}\n\ndeclare module \"font-manager\" {\n    declare const fontManager: FontManager\n\n    export default fontManager\n}\n"
  },
  {
    "path": "ACCOUNTING.md",
    "content": "# ONI\n\n## Accounting\n\nThis file will contain a monthly report including:\n\n* Incoming contributions\n* How the contributions are distributed, in accordance with the project's goals\n\nThe initial plan for allocation is as follows:\n\n* 10% - Vim - Contribute to Bram's charity of choice\n* 20% - Neovim Development\n* 35% - Paid to contributors via bounties\n* 35% - Paid to maintainer\n\nYour contributions help keep this project alive!\n\n### March 2017\n\nIN-PROGRESS\n"
  },
  {
    "path": "BACKERS.md",
    "content": "# Sponsors & Backers\n\nOni is an MIT-licensed open-source project. It's an independent project without the backing of a large company, and the ongoing development is made possible by our backers.\n\nThanks you to all our backers for making Oni possible!\n\n## VIP Backers via BountySource\n\n*   @jordwalke\n*   @mhartington\n*   @MikaAK\n*   @emolitor\n\n## VIP Backers via Patreon\n\n*   @mikl\n*   Tom Boland\n*   Simon Smith\n*   [JavaScript.Ninja](https://www.patreon.com/search?q=javascript.ninja)\n*   Mika Kalathil\n*   Franky Chung\n*   Jackie McGhee\n\n## Backers via BountySource\n\n*   @adambard\n*   @akin_so\n*   @ayohan\n*   @badosu\n*   @josemarluedke\n*   @napcode\n*   @robtrac\n*   @rrichardson\n*   @sbuljac\n*   @parkerault\n*   @city41\n*   @nithesh\n*   @erandac\n*   @appelgriebsch\n*   Mateusz Wieloch\n\n## Backers via PayPal\n\n*   @mchalkley\n*   @am2605\n*   Nathan Ensmenger\n*   Cesar Avitia\n\n## Backers via OpenCollective\n\n*   Tal Amuyal\n*   Akinola Sowemimo\n*   Martijn Arts\n*   Amadeus Folego\n*   Kiyoshi Murata\n*   @Himura2la\n*   Frederick Gnodtke\n\n## Backers via Patreon\n\n*   @bennettrogers\n*   @muream\n*   Johnnie Hård\n*   @robin-pham\n*   Ryan Campbell\n*   Balint Fulop\n*   Quasar Jarosz\n*   Channing Conger\n*   Clinton Bloodworth\n*   Lex Song\n*   Paul Baumgart\n*   Kaiden Sin\n*   Troy Vitullo\n*   Leo Critchley\n*   Patrick Massot\n*   Jerome Pellois\n*   Wesley Moore\n*   Kim Fiedler\n*   Nicolaus Hepler\n*   Nick Price\n*   Domenico Maisano\n*   Daniel Polanco\n*   Eric Hall\n*   Dimas Cyriaco\n*   Carlos Coves Prieto\n*   Bryan Germann\n*   James Herdman\n*   Wayan Jimmy\n*   Alex\n*   Phil Plückthun\n*   Norikazu Hayashi\n*   Paul Anderson\n*   Thomas Frick\n*   LinuxLefty\n*   Leon Bogaert\n*   Jorrit Siebelink\n*   Zac Sims\n*   Doug Beney\n*   Aditya Gudimella\n*   Michal Hantl\n*   Lennaert Meijvogel\n*   Jonas Strømsodd\n*   Trevor Barton\n*   Tercio de Melo\n*   Jon Plotner\n*   Patrick Ball\n*   Grégory Reinbold\n*   Antti Holvikari\n*   Christopher Auer\n*   Daniel Falk\n*   David Froger\n*   Dominic Saadi\n*   Gianni Chiappetta\n*   Jake Swanson\n*   James Herdman\n*   Jannis Kaiser\n*   Kosuke Hamada\n*   Lance\n*   Marius Gripsgard\n*   Matti Klock\n*   Selwyn\n*   Saito Nakamura\n*   artalar\n*   Jeff Hertzler\n*   Drew Lazzeri\n*   Bob Gunion\n*   Daniel Blanco\n*   Philip Larson\n*   Josemar Luedke\n*   Mateusz Wieloch\n*   Marc Agbanchenou\n*   Andrew Myers\n*   Corey T Kump\n*   Claudia Hardman\n*   Krakonos\n*   sschwarzer\n*   Andrew Cobby\n*   Imobach González Sosa\n*   Devin\n*   Antonio de Jesus Ochoa Solano\n*   Parker Ault\n*   Rauan Mayemir\n*   Matt Rockwell\n*   Anatoly\n*   Kino\n*   Andrey Popp\n*   James Atkinson\n*   Yohan Lee\n*   Sime Buljac\n*   Brian Recchia\n*   Brandon Ubben\n*   Devin\n*   sschwarzer\n*   Logan Call\n*   Adam Recvlohe\n*   Shawn MacIntyre\n*   Alexandre Mounton-Brady\n*   Todd Epple\n*   Jacob Mischka\n*   Javier Chavarri\n*   David Izquierdo\n*   Richou Degenne\n*   Tyler Compton\n*   Marcos Ojeda\n*   Daniel Martinez\n*   Anthony Mittaz\n*   Yohanes Bandung\n*   Jaap Frölich\n*   Aaron Franks\n*   Adam Howard\n*   Jeff See\n*   آرين دانشور\n*   Alpha Shuro\n*   Sundeep Malladi\n*   Sylvan\n*   Vitezslav Homolka\n*   Jens Aronsson\n*   Benjie Gillam\n*   Christophe Riolo\n*   Jih-Chi Lee\n*   Paul Naranja\n*   Krisztián Szegi\n*   Karlin Fox\n*   Wayne Maurer\n*   Ragnar Hardarson\n*   Andrew Herron\n*   TxH\n*   Richard Feldman\n*   ELLIOTCABLE\n*   Alexey Alekhin\n*   Gal Schlezinger\n*   Michael Jackson\n*   Tim Gebauer\n*   David Gregory\n*   Tony André Haugen\n*   Matthieu Tabuteau\n*   Rich Dean\n*   Dmytro Gladkyi\n*   Brett Eisenberg\n*   Oswaldo Caballero\n*   Goku\n*   Sawyer Bergeron\n*   Igor Matuszewski\n*   Visate\n*   Edward Vetter-Drake\n*   Steven Volocyk\n*   Danny Martini\n*   Mitchell Hanberg\n\n\n<a href=\"https://opencollective.com/oni/tiers/backer/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/0/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/1/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/2/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/3/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/4/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/5/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/6/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/7/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/8/avatar.png\"></a>\n<a href=\"https://opencollective.com/oni/tiers/backer/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/tiers/backer/9/avatar.png\"></a>\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at admin@onivim.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribute\n\n## Introduction\n\nFirst, thank you for considering contributing to oni! It's people like you that make the open source community such a great community! 😊\n\nWe welcome any type of contribution, not only code. You can help with\n\n*   **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)\n*   **Marketing**: writing blog posts, howto's, printing stickers, ...\n*   **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...\n*   **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them.\n*   **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/oni).\n\n## Your First Contribution\n\nWorking on your first Pull Request? You can learn how from this _free_ series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).\n\n## Submitting code\n\nAny code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests. We welcome and appreciate pull requests!\n\n## Code review guidelines\n\n*   Keep PRs **small and scoped**. The bigger the pull request, the longer it will take to review and merge. Break down large pull requests into smaller incremental chunks - this will help catch issues earlier and be easier on both you and the maintainer.\n*   Following from the previous bullet point, **do not include unrelated changes in a PR**. It can be tempting to include extra styling changes or additional functionality, but these should be added as separate PRs.\n*   Think of each PR as **improving the quality of the codebase**. Codebases tend towards entropy and disorder unless actively managed - make sure that your change moves the quality needle in the right direction. This can take a variety of forms, including adding test coverage, reducing coupling, etc. _As we are a small team moving fast, we cannot afford to accumulate technical debt._\n*   If there is ambiguity in terms of design, architecture, or implementation, it's best to get **feedback before implementing**, to save both you and the maintainer time. If you're not sure, feel free to ask!\n*   For your first few PRs, **don't try and change the world** - pick some small issues and get familiar with the codebase. Then, work your way up to bigger issues - this will set you up for success.\n\nPRs require approval from one other person, either a maintainer or a contributor. Keep in mind that when you approve code, you are accountable for it, too! Reviewers are the gatekeepers of quality and ensuring adherence to the guidelines above.\n\n## Financial contributions\n\nWe also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/oni).\nAnyone can file an expense. If the expense makes sense for the development of the community, it will be \"merged\" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.\n\n### Bounties\n\nThe primary allotment of our [open collective](https://opencollective.com/oni) budget is dedicated to bounties. Developing features and fixing bugs is a lot of work, and those go directly to the developers doing this work via bounties. It is the role of the _maintainer_ to set bounties and clear completion criteria. Issues that have a bounty associated with them will have a `bounty` label as well as an amount, ie, `bounty-50` means a $50 bounty.\n\n*   Guidelines:\n    *   The fix for the bug/feature/issue _MUST_ be complete and _MUST_ be covered by tests to be eligible for a bounty.\n    *   Any associated documentation relevant to the bug/feature _MUST_ be updated.\n    *   If you begin working on an issue with an associated bounty, open a PR with \"WIP\" and the bug number in the title, as well as reference the issue #. This is important to reduce duplicate work.\n\n#### Claiming a bounty\n\n*   Upon completion of an issue with an associated bounty, bounties are payable by [Submitting an Expense](https://opencollective.com/oni/expenses/new) on our [OpenCollective](https://opencollective.com/oni). Note that OpenCollective requires a PDF or Photo of an expense form for an expense claim to be accepted - more information, including an example expense form can be found [here](https://opencollective.com/faq#expense). Check out our [expenses](https://opencollective.com/oni/expenses#) page for an example.\n*   A collaborator will approve the expense once we have verified it meets the criteria outlined above (complete fix, covered by tests, associated documentation updated)\n\nIf you questions about the guidelines, please don't hesitate to contact the maintainer.\n\n## Roles\n\nThere are various roles and responsibilities in managing an open-source project. Users that are active and have a positive impact on the project and community will be recognized and have the option of assuming additional responsibilities.\n\n*   **Maintainer** - A maintainer communicates goals and drives the vision for the project. The maintainer is responsible for breaking down hurdles and supporting contributors. In addition, the maintainer triages issues, produces releases, assigns bounties, and establishes completion criteria. Today, there is one maintainer, but that isn't a strict requirement.\n*   **Collaborator** - A collaborator is an established member of the project that is recognized for their impact and contributions. They can triage and close issues, approve PRs from other contributors / collaborators, and can approve expenses on our [open collective](https://opencollective.com/oni)\n*   **Contributor** - A contributor is a developer that has submitted a successful PR for the project.\n\n### Becoming a collaborator\n\nA collaborator is a contributor who has been recognized for the impact they've had on the project, over a sustained period of time. In general, this means the following:\n\n*   **Supporting the community** - helping others in issues and chat, supporting new developers, creating a positive and supportive environment.\n*   **Technical impact** - involvement in a core technical piece of the editor, or a broad impact on the ecosystem.\n*   **Positive and collaborative mindset** - creating good vibes, willingness to give and receive constructive feedback, being a team player.\n\n## Questions\n\nIf you have any questions, create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).\nYou can also reach us at hello@oni.opencollective.com.\n\n## Credits\n\n### Contributors\n\nThank you to all the people who have already contributed to oni!\n<a href=\"graphs/contributors\"><img src=\"https://opencollective.com/oni/contributors.svg?width=890\" /></a>\n\n### Backers\n\nThank you to all our backers! [[Become a backer](https://opencollective.com/oni#backer)]\n\n<a href=\"https://opencollective.com/oni#backers\" target=\"_blank\"><img src=\"https://opencollective.com/oni/backers.svg?width=890\"></a>\n\n### Sponsors\n\nThank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/oni#sponsor))\n\n<a href=\"https://opencollective.com/oni/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/oni/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/oni/sponsor/9/avatar.svg\"></a>\n\n<!-- This `CONTRIBUTING.md` is based on @nayafia's template https://github.com/nayafia/contributing-template -->\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 \n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "---\n__NOTE:__ This repository is unmaintained - we are focusing on [Onivim 2](https://github.com/onivim/oni2) and [libvim](https://github.com/onivim/libvim).\n---\n\n<p align=\"center\">\n\t<img src=\"./assets/oni-header.png\" alt=\"Logo\">\n    <h3 align=\"center\">Modern Modal Editing</h3>\n</p>\n\n<p align=\"center\">\n\t<a href=\"https://travis-ci.org/onivim/oni\">\n\t\t<img src=\"https://travis-ci.org/onivim/oni.svg?branch=master\" alt=\"Build Status\">\n\t</a>\n\t<a href=\"https://ci.appveyor.com/project/oni/oni\">\n\t\t<img src=\"https://ci.appveyor.com/api/projects/status/s13bs7ail9ihkpnm?svg=true\" alt=\"Build Status\">\n\t</a>\n\t<a href=\"https://codecov.io/gh/onivim/oni\">\n\t\t<img src=\"https://codecov.io/gh/onivim/oni/branch/master/graph/badge.svg\" alt=\"codecov\">\n\t</a>\n</p>\n\n<p align=\"center\">\n\t<a href=\"https://discord.gg/7maEAxV\">\n\t\t<img src=\"https://img.shields.io/discord/417774914645262338.svg\" alt=\"Join the chat on discord!\">\n\t</a>\n\t<a href=\"https://github.com/onivim/oni/releases\">\n\t\t<img src=\"https://img.shields.io/github/downloads/onivim/oni/total.svg\" alt=\"Total Downloads\">\n\t</a>\n</p>\n\n## Introduction\n\nOni is a new kind of editor, focused on maximizing productivity - combining _modal editing_ with features you expect in modern editors. Oni is built with [neovim](https://github.com/neovim/neovim), and inspired by [VSCode](https://github.com/Microsoft/vscode), [Atom](https://atom.io/), [LightTable](http://lighttable.com/), and [Emacs](https://www.gnu.org/software/emacs/)\n\nThe vision of Oni is to build an editor that allows you to go from _thought to code_ as easily as possible - bringing together the raw editing power of Vim, the feature capabilities of Atom/VSCode, and a powerful and intuitive extensibility model - wrapped up in a beautiful package.\n\n<p align=\"center\">\n    <img src=\"https://user-images.githubusercontent.com/13532591/36127305-9c7b6b80-1011-11e8-85dd-0345788c0b56.png\"/>\n</p>\n\nCheck out [Releases](https://github.com/onivim/oni/releases) for the latest binaries, or [Build Oni](https://github.com/onivim/oni/wiki/Development) from source. Consider making a donation via [OpenCollective](https://opencollective.com/oni) [BountySource](https://salt.bountysource.com/teams/oni) if you find this project useful!\n\n## Features\n\nOni brings several IDE-like integrations to neovim:\n\n*   [Embedded Browser](https://github.com/onivim/oni/wiki/Features#embedded-browser)\n*   [Quick Info](https://github.com/onivim/oni/wiki/Features#quick-info)\n*   [Code Completion](https://github.com/onivim/oni/wiki/Features#code-completion)\n*   [Syntax / Compilation Errors](https://github.com/onivim/oni/wiki/Features#syntax--compilation-errors)\n*   [Fuzzy Finding](https://github.com/onivim/oni/wiki/Features#fuzzy-finder)\n*   [Status Bar](https://github.com/onivim/oni/wiki/Features#status-bar)\n*   [Interactive Tutorial](https://github.com/onivim/oni/wiki/Features#interactive-tutorial)\n\nAnd more coming - check out our [Roadmap](https://github.com/onivim/oni/wiki/Roadmap)\n\nOni is cross-platform and supports Windows, Mac, and Linux.\n\n> If you're a Vim power user, and don't need all these features, check out our [minimal configuration](https://github.com/onivim/oni/wiki/How-To:-Minimal-Oni-Configuration).\n\n## Installation\n\nWe have installation guides for each platform:\n\n*   [Windows](https://github.com/onivim/oni/wiki/Installation-Guide#windows)\n*   [Mac](https://github.com/onivim/oni/wiki/Installation-Guide#mac)\n*   [Linux](https://github.com/onivim/oni/wiki/Installation-Guide#linux)\n\nThe latest binaries are available on our [Releases](https://github.com/onivim/oni/releases) page, and if you'd prefer to build from source, check out our [Development](https://github.com/onivim/oni/wiki/Development) guide.\n\n## Goals\n\nThe goal of this project is to provide both the full-fledged Vim experience, with no compromises, while pushing forward to enable new productivity scenarios.\n\n*   **Modern UX** - The Vim experience should not be compromised by terminal limitations.\n*   **Rich plugin development** - using JavaScript, instead of VimL.\n*   **Cross-platform support** - across Windows, OS X, and Linux.\n*   **Batteries included** - rich features are available out of the box - minimal setup needed to be productive.\n*   **Performance** - no compromises, Vim is fast, and Oni should be fast too.\n*   **Ease Learning Curve** - without sacrificing the Vim experience.\n\nVim is an incredible tool for manipulating _text_ at the speed of thought. With a composable, modal command language, it is no wonder that Vim usage is still prevalent today.\n\nHowever, going from thought to _code_ has some different challenges than going from thought to _text_. Code editors today provide several benefits that help to reduce **cognitive load** when writing code, and that benefit is tremendously important - not only in terms of pure coding efficiency and productivity, but also in making the process of writing code enjoyable and fun.\n\nThe goal of this project is to give an editor that gives the best of both worlds - the power, speed, and flexibility of using Vim for manipulating text, as well as the rich tooling that comes with an IDE. We want to make coding as efficient, fast, and fun as we can!\n\n## Documentation\n\n*   Check out the [Wiki](https://github.com/onivim/oni/wiki) for documentation on how to use and modify Oni.\n*   [FAQ](https://github.com/onivim/oni/wiki/FAQ)\n*   [Roadmap](https://github.com/onivim/oni/wiki/Roadmap)\n\n## Available Plugins\n\nSome available plugins created by Oni users are listed below (if you'd like to add your\nplugin to this list please create a PR updating this **README** with the details).\n\n*   [Oni Touchbar Plugin](https://github.com/jordan-arenstein/oni-plugin-touchbar) - by [jordan-arenstein](https://github.com/jordan-arenstein?tab=overview&from=2018-07-01&to=2018-07-31)\n*   [quickFind](https://github.com/marene/quickFind) - by [marene](https://github.com/marene)\n    *   Themes\n        *   [Night Owl](https://github.com/Akin909/oni-theme-night-owl)\n\n## Contributing\n\nThere many ways to get involved & contribute to Oni:\n\n*   Thumbs up existing [issues](https://github.com/onivim/oni/issues) if they impact you.\n*   [Create an issue](https://github.com/onivim/oni/issues) for bugs or new features.\n*   Review and update our [documentation](https://github.com/onivim/oni/wiki).\n*   Try out the latest [released build](https://github.com/onivim/oni/releases).\n*   Help us [develop](https://github.com/onivim/oni/wiki/Development):\n    *   Review [PRs](https://github.com/onivim/oni/pulls)\n    *   Submit a bug fix or feature\n    *   Add test cases\n*   Create a blog post or YouTube video\n*   Follow us on [Twitter](https://twitter.com/oni_vim)\n\n## Acknowledgements\n\nOni is an independent project and is made possible by the support of some exceptional people. Big thanks to the following people for helping to realize this project:\n\n*   the [neovim team](https://neovim.io/), especially [justinmk](https://github.com/justinmk) and [tarruda](https://github.com/tarruda) - Oni would not be possible without their vision\n*   [jordwalke](https://github.com/jordwalke) for his generous support, inspiration, and ideas. And React ;)\n*   [keforbes](https://github.com/keforbes) for helping to get this project off the ground\n*   [Akin909](https://github.com/Akin909) for his extensive contributions\n*   [CrossR](https://github.com/CrossR) for polishing features and configurations\n*   [Cryza](https://github.com/Cryza) for the webgl renderer\n*   [tillarnold](https://github.com/tillarnold) for giving us the `oni` npm package name\n*   [mhartington](https://github.com/mhartington) for his generous support\n*   [badosu](https://github.com/badosu) for his support, contributions, and managing the AUR releases\n*   All our current monthly [sponsors](https://salt.bountysource.com/teams/oni/supporters) and [backers](BACKERS.md)\n*   All of our [contributors](https://github.com/onivim/oni/graphs/contributors) - thanks for helping to improve this project!\n\nSeveral other great neovim front-end UIs [here](https://github.com/neovim/neovim/wiki/Related-projects) served as a reference, especially [NyaoVim](https://github.com/rhysd/NyaoVim) and [VimR](https://github.com/qvacua/vimr). I encourage you to check those out!\n\nThank you!\n\n## Contributors\n\nThis project exists thanks to all the people who have [contributed](CONTRIBUTING.md):\n<a href=\"https://github.com/onivim/oni/graphs/contributors\"><img src=\"https://opencollective.com/oni/contributors.svg?width=890\" /></a>\n\n## License\n\nMIT License. Copyright (c) Bryan Phelps\n\nWindows and OSX have a bundled version of Neovim, which is covered under [Neovim's license](https://github.com/neovim/neovim/blob/master/LICENSE)\n\n### Bundled Plugins\n\nBundled plugins have their own license terms. These include:\n\n*   [typescript-vim](https://github.com/leafgarland/typescript-vim) (`oni/vim/core/typescript.vim`)\n*   [targets.vim](https://github.com/wellle/targets.vim) (`oni/vim/default/bundle/targets.vim`)\n*   [vim-commentary](https://github.com/tpope/vim-commentary) (`oni/vim/default/bundle/vim-commentary`)\n*   [vim-unimpaired](https://github.com/tpope/vim-unimpaired) (`oni/vim/default/bundle/vim-unimpaired`)\n*   [vim-surround](https://github.com/tpope/vim-surround) (`oni/vim/default/bundle/vim-surround`)\n*   [vim-reasonml](https://github.com/reasonml-editor/vim-reason) (`.vim` files in `oni/vim/core/oni-plugin-reasonml`)\n"
  },
  {
    "path": "appveyor.yml",
    "content": "# Test against the latest version of this Node.js version\nenvironment:\n    nodejs_version: \"8\"\n\nos: unstable\n\nbranches:\n    only:\n        - master\n        - /^release.*/\n\n# Skip CI build if the changes match these rules exactly.\n# Ie, if the BACKERS.md file is changed, we don't need to build.\nskip_commits:\n    files:\n        - \"**/*.md\"\n\ncache:\n    - .oni_build_cache -> package.json\n\nplatform:\n    - x86\n    - x64\n\n# Install scripts. (runs after repo cloning)\ninstall:\n    # Ensure the Git Submoduldes have been pulled down too\n    - git submodule update --init --recursive\n    # Get the latest stable version of Node.js or io.js\n    - ps: Install-Product node $env:nodejs_version\n    # Workaround https://github.com/npm/npm/issues/18380\n    - npm install -g yarn\n    - node --version\n    - npm --version\n    # install modules\n    - yarn install\n    - yarn run check-cached-binaries\n\n# Post-install test scripts.\ntest_script:\n    - powershell build/script/appveyor-test.ps1\n\n# Don't actually build.\nbuild: off\n"
  },
  {
    "path": "browser/src/App.ts",
    "content": "/**\n * App.ts\n *\n * Entry point for the Oni application - managing the overall lifecycle\n */\n\nimport { ipcRenderer, remote } from \"electron\"\nimport * as fs from \"fs\"\nimport * as minimist from \"minimist\"\nimport * as path from \"path\"\n\nimport { IDisposable } from \"oni-types\"\n\nimport * as Log from \"oni-core-logging\"\nimport * as Performance from \"./Performance\"\nimport * as Utility from \"./Utility\"\n\nimport { IConfigurationValues } from \"./Services/Configuration/IConfigurationValues\"\n\nconst editorManagerPromise = import(\"./Services/EditorManager\")\nconst sharedNeovimInstancePromise = import(\"./neovim/SharedNeovimInstance\")\n\nexport type QuitHook = () => Promise<void>\n\nlet _quitHooks: QuitHook[] = []\nconst _initializePromise: Utility.ICompletablePromise<void> = Utility.createCompletablePromise<\n    void\n>()\n\nexport const registerQuitHook = (quitHook: QuitHook): IDisposable => {\n    _quitHooks.push(quitHook)\n\n    const dispose = () => {\n        _quitHooks = _quitHooks.filter(qh => qh !== quitHook)\n    }\n\n    return {\n        dispose,\n    }\n}\n\nexport const quit = async (): Promise<void> => {\n    Log.info(`[App::quit] called with ${_quitHooks.length} quitHooks`)\n    const promises = _quitHooks.map(async qh => {\n        Log.info(\"[App.quit] Waiting for quit hook...\")\n        await qh()\n        Log.info(\"[App.quit] Quit hook completed successfully\")\n    })\n    await Promise.all([promises])\n    // On mac we should quit the application when the user press Cmd + Q\n    if (process.platform === \"darwin\") {\n        Log.info(\"[App::quit] quitting app\")\n        remote.app.quit()\n    }\n    Log.info(\"[App::quit] completed\")\n}\n\nexport const waitForStart = (): Promise<void> => {\n    return _initializePromise.promise\n}\n\nexport const start = async (args: string[]): Promise<void> => {\n    Performance.startMeasure(\"Oni.Start\")\n\n    const UnhandledErrorMonitor = await import(\"./Services/UnhandledErrorMonitor\")\n    UnhandledErrorMonitor.activate()\n\n    const Shell = await import(\"./UI/Shell\")\n    Shell.activate()\n\n    const configurationPromise = import(\"./Services/Configuration\")\n    const configurationCommandsPromise = import(\"./Services/Configuration/ConfigurationCommands\")\n    const debugPromise = import(\"./Services/Debug\")\n    const pluginManagerPromise = import(\"./Plugins/PluginManager\")\n    const themesPromise = import(\"./Services/Themes\")\n    const iconThemesPromise = import(\"./Services/IconThemes\")\n\n    const sessionManagerPromise = import(\"./Services/Sessions\")\n    const sidebarPromise = import(\"./Services/Sidebar\")\n    const overlayPromise = import(\"./Services/Overlay\")\n    const statusBarPromise = import(\"./Services/StatusBar\")\n    const startEditorsPromise = import(\"./startEditors\")\n\n    const menuPromise = import(\"./Services/Menu\")\n\n    const browserWindowConfigurationSynchronizerPromise = import(\"./Services/BrowserWindowConfigurationSynchronizer\")\n    const colorsPromise = import(\"./Services/Colors\")\n    const tokenColorsPromise = import(\"./Services/TokenColors\")\n    const diagnosticsPromise = import(\"./Services/Diagnostics\")\n    const globalCommandsPromise = import(\"./Services/Commands/GlobalCommands\")\n    const inputManagerPromise = import(\"./Services/InputManager\")\n    const languageManagerPromise = import(\"./Services/Language\")\n    const vcsManagerPromise = import(\"./Services/VersionControl\")\n    const notificationsPromise = import(\"./Services/Notifications\")\n    const snippetPromise = import(\"./Services/Snippets\")\n    const keyDisplayerPromise = import(\"./Services/KeyDisplayer\")\n    const taksPromise = import(\"./Services/Tasks\")\n    const terminalPromise = import(\"./Services/Terminal\")\n    const workspacePromise = import(\"./Services/Workspace\")\n    const workspaceCommandsPromise = import(\"./Services/Workspace/WorkspaceCommands\")\n    const windowManagerPromise = import(\"./Services/WindowManager\")\n    const multiProcessPromise = import(\"./Services/MultiProcess\")\n\n    const themePickerPromise = import(\"./Services/Themes/ThemePicker\")\n    const cssPromise = import(\"./CSS\")\n    const completionProvidersPromise = import(\"./Services/Completion/CompletionProviders\")\n\n    const parsedArgs = minimist(args, { string: \"_\" })\n    const currentWorkingDirectory = process.cwd()\n    const normalizedFiles = parsedArgs._.map(\n        arg => (path.isAbsolute(arg) ? arg : path.join(currentWorkingDirectory, arg)),\n    )\n\n    const filesToOpen = normalizedFiles.filter(f => {\n        if (fs.existsSync(f)) {\n            return fs.statSync(f).isFile()\n        } else {\n            return true\n        }\n    })\n    const foldersToOpen = normalizedFiles.filter(\n        f => fs.existsSync(f) && fs.statSync(f).isDirectory(),\n    )\n\n    Log.info(\"Files to open: \" + JSON.stringify(filesToOpen))\n    Log.info(\"Folders to open: \" + JSON.stringify(foldersToOpen))\n\n    let workspaceToLoad = null\n\n    // If a folder has been specified, we'll change directory to it\n    if (foldersToOpen.length > 0) {\n        workspaceToLoad = foldersToOpen[0]\n    } else if (filesToOpen.length > 0) {\n        workspaceToLoad = path.dirname(filesToOpen[0])\n    }\n\n    // Helper for debugging:\n    Performance.startMeasure(\"Oni.Start.Config\")\n\n    const { configuration } = await configurationPromise\n\n    const initialConfigParsingErrors = configuration.getErrors()\n    if (initialConfigParsingErrors && initialConfigParsingErrors.length > 0) {\n        initialConfigParsingErrors.forEach((err: Error) => Log.error(err))\n    }\n\n    const configChange = (newConfigValues: Partial<IConfigurationValues>) => {\n        let prop: keyof IConfigurationValues\n        for (prop in newConfigValues) {\n            if (newConfigValues[prop]) {\n                Shell.Actions.setConfigValue(prop, newConfigValues[prop])\n            }\n        }\n    }\n\n    configuration.start()\n\n    configChange(configuration.getValues()) // initialize values\n    configuration.onConfigurationChanged.subscribe(configChange)\n    Performance.endMeasure(\"Oni.Start.Config\")\n\n    const PluginManager = await pluginManagerPromise\n    PluginManager.activate(configuration)\n    const pluginManager = PluginManager.getInstance()\n\n    const developmentPlugin = parsedArgs[\"plugin-develop\"]\n    let developmentPluginError: { title: string; errorText: string }\n\n    if (typeof developmentPlugin === \"string\") {\n        Log.info(\"Registering development plugin: \" + developmentPlugin)\n        if (fs.existsSync(developmentPlugin)) {\n            pluginManager.addDevelopmentPlugin(developmentPlugin)\n        } else {\n            developmentPluginError = {\n                title: \"Error parsing arguments\",\n                errorText: \"Could not find plugin: \" + developmentPlugin,\n            }\n            Log.warn(developmentPluginError.errorText)\n        }\n    } else if (typeof developmentPlugin === \"boolean\") {\n        developmentPluginError = {\n            title: \"Error parsing arguments\",\n            errorText: \"--plugin-develop must be followed by a plugin path\",\n        }\n        Log.warn(developmentPluginError.errorText)\n    }\n\n    Performance.startMeasure(\"Oni.Start.Plugins.Discover\")\n    pluginManager.discoverPlugins()\n    Performance.endMeasure(\"Oni.Start.Plugins.Discover\")\n\n    const oniApi = pluginManager.getApi()\n\n    Performance.startMeasure(\"Oni.Start.Themes\")\n    const Themes = await themesPromise\n    const IconThemes = await iconThemesPromise\n    await Promise.all([\n        Themes.activate(configuration, pluginManager),\n        IconThemes.activate(configuration, pluginManager),\n    ])\n\n    const Colors = await colorsPromise\n    Colors.activate(configuration, Themes.getThemeManagerInstance())\n    const colors = Colors.getInstance()\n    Shell.initializeColors(Colors.getInstance())\n    Performance.endMeasure(\"Oni.Start.Themes\")\n\n    const TokenColors = await tokenColorsPromise\n    TokenColors.activate(configuration, Themes.getThemeManagerInstance())\n\n    const BrowserWindowConfigurationSynchronizer = await browserWindowConfigurationSynchronizerPromise\n    BrowserWindowConfigurationSynchronizer.activate(configuration, Colors.getInstance())\n\n    const { editorManager } = await editorManagerPromise\n\n    const Workspace = await workspacePromise\n    Workspace.activate(configuration, editorManager, workspaceToLoad)\n    const workspace = Workspace.getInstance()\n\n    const WindowManager = await windowManagerPromise\n    const MultiProcess = await multiProcessPromise\n\n    MultiProcess.activate(WindowManager.windowManager)\n\n    const StatusBar = await statusBarPromise\n    StatusBar.activate(configuration)\n\n    const Overlay = await overlayPromise\n    Overlay.activate()\n    const overlayManager = Overlay.getInstance()\n\n    const sneakPromise = import(\"./Services/Sneak\")\n    const { commandManager } = await import(\"./Services/CommandManager\")\n    const Sneak = await sneakPromise\n    Sneak.activate(colors, commandManager, configuration, overlayManager)\n\n    const Menu = await menuPromise\n    Menu.activate(configuration, overlayManager)\n    const menuManager = Menu.getInstance()\n\n    const Notifications = await notificationsPromise\n    Notifications.activate(configuration, overlayManager)\n    const notifications = Notifications.getInstance()\n\n    if (typeof developmentPluginError !== \"undefined\") {\n        const notification = notifications.createItem()\n        notification.setContents(developmentPluginError.title, developmentPluginError.errorText)\n        notification.setLevel(\"error\")\n        notification.onClick.subscribe(() =>\n            commandManager.executeCommand(\"oni.config.openConfigJs\"),\n        )\n        notification.show()\n    }\n\n    configuration.onConfigurationError.subscribe(err => {\n        const notification = notifications.createItem()\n        notification.setContents(\"Error Loading Configuration\", err.toString())\n        notification.setLevel(\"error\")\n        notification.onClick.subscribe(() =>\n            commandManager.executeCommand(\"oni.config.openConfigJs\"),\n        )\n        notification.show()\n    })\n\n    UnhandledErrorMonitor.start(configuration, Notifications.getInstance())\n\n    const Tasks = await taksPromise\n    Tasks.activate(menuManager)\n    const tasks = Tasks.getInstance()\n\n    const LanguageManager = await languageManagerPromise\n    LanguageManager.activate(oniApi)\n    const languageManager = LanguageManager.getInstance()\n\n    Performance.startMeasure(\"Oni.Start.Editors\")\n    const SharedNeovimInstance = await sharedNeovimInstancePromise\n    const { startEditors } = await startEditorsPromise\n\n    const CSS = await cssPromise\n    CSS.activate()\n\n    const Snippets = await snippetPromise\n    Snippets.activate(commandManager, configuration)\n\n    Shell.Actions.setLoadingComplete()\n\n    const Diagnostics = await diagnosticsPromise\n    const diagnostics = Diagnostics.getInstance()\n\n    const CompletionProviders = await completionProvidersPromise\n    CompletionProviders.activate(languageManager)\n\n    const initializeAllEditors = async () => {\n        await startEditors(\n            filesToOpen,\n            Colors.getInstance(),\n            CompletionProviders.getInstance(),\n            configuration,\n            diagnostics,\n            languageManager,\n            menuManager,\n            overlayManager,\n            pluginManager,\n            Snippets.getInstance(),\n            Themes.getThemeManagerInstance(),\n            TokenColors.getInstance(),\n            workspace,\n        )\n\n        await SharedNeovimInstance.activate(configuration, pluginManager)\n    }\n\n    await Promise.race([Utility.delay(5000), initializeAllEditors()])\n    Performance.endMeasure(\"Oni.Start.Editors\")\n\n    Performance.startMeasure(\"Oni.Start.Sidebar\")\n    const Sidebar = await sidebarPromise\n    const Learning = await import(\"./Services/Learning\")\n    const Explorer = await import(\"./Services/Explorer\")\n    const Search = await import(\"./Services/Search\")\n\n    Sidebar.activate(configuration, workspace)\n    const sidebarManager = Sidebar.getInstance()\n\n    const VCSManager = await vcsManagerPromise\n    VCSManager.activate(oniApi, sidebarManager, notifications)\n\n    Explorer.activate(oniApi, configuration, Sidebar.getInstance())\n    Learning.activate(\n        commandManager,\n        configuration,\n        editorManager,\n        overlayManager,\n        Sidebar.getInstance(),\n        WindowManager.windowManager,\n    )\n\n    const Sessions = await sessionManagerPromise\n    Sessions.activate(oniApi, sidebarManager)\n\n    Performance.endMeasure(\"Oni.Start.Sidebar\")\n\n    const createLanguageClientsFromConfiguration =\n        LanguageManager.createLanguageClientsFromConfiguration\n\n    diagnostics.start(languageManager)\n\n    const Browser = await import(\"./Services/Browser\")\n    Browser.activate(commandManager, configuration, editorManager)\n\n    Performance.startMeasure(\"Oni.Start.Activate\")\n    const api = pluginManager.startApi()\n    Search.activate(api)\n    configuration.activate(api)\n\n    Snippets.activateProviders(\n        commandManager,\n        CompletionProviders.getInstance(),\n        configuration,\n        pluginManager,\n    )\n\n    createLanguageClientsFromConfiguration(configuration.getValues())\n\n    const { inputManager } = await inputManagerPromise\n\n    const autoClosingPairsPromise = import(\"./Services/AutoClosingPairs\")\n\n    const ConfigurationCommands = await configurationCommandsPromise\n    ConfigurationCommands.activate(commandManager, configuration, editorManager)\n\n    const AutoClosingPairs = await autoClosingPairsPromise\n    AutoClosingPairs.activate(configuration, editorManager, inputManager, languageManager)\n\n    const GlobalCommands = await globalCommandsPromise\n    GlobalCommands.activate(commandManager, editorManager, menuManager, tasks)\n\n    const Debug = await debugPromise\n    Debug.activate(commandManager)\n\n    const WorkspaceCommands = await workspaceCommandsPromise\n    WorkspaceCommands.activateCommands(\n        configuration,\n        editorManager,\n        Snippets.getInstance(),\n        workspace,\n    )\n\n    const Preview = await import(\"./Services/Preview\")\n    Preview.activate(commandManager, configuration, editorManager)\n\n    const KeyDisplayer = await keyDisplayerPromise\n    KeyDisplayer.activate(\n        commandManager,\n        configuration,\n        editorManager,\n        inputManager,\n        overlayManager,\n    )\n\n    const ThemePicker = await themePickerPromise\n    ThemePicker.activate(configuration, menuManager, Themes.getThemeManagerInstance())\n\n    const Bookmarks = await import(\"./Services/Bookmarks\")\n    Bookmarks.activate(configuration, editorManager, Sidebar.getInstance())\n\n    const PluginsSidebarPane = await import(\"./Plugins/PluginSidebarPane\")\n    PluginsSidebarPane.activate(commandManager, configuration, pluginManager, sidebarManager)\n\n    const Terminal = await terminalPromise\n    Terminal.activate(commandManager, configuration, editorManager)\n\n    const Particles = await import(\"./Services/Particles\")\n    Particles.activate(commandManager, configuration, editorManager, overlayManager)\n\n    const PluginConfigurationSynchronizer = await import(\"./Plugins/PluginConfigurationSynchronizer\")\n    PluginConfigurationSynchronizer.activate(configuration, pluginManager)\n\n    const Achievements = await import(\"./Services/Learning/Achievements\")\n    const achievements = Achievements.getInstance()\n\n    if (achievements) {\n        Debug.registerAchievements(achievements)\n        Sneak.registerAchievements(achievements)\n        Browser.registerAchievements(achievements)\n    }\n\n    Performance.endMeasure(\"Oni.Start.Activate\")\n\n    checkForUpdates()\n\n    commandManager.registerCommand({\n        command: \"oni.quit\",\n        name: null,\n        detail: null,\n        execute: () => quit(),\n    })\n\n    Performance.endMeasure(\"Oni.Start\")\n    ipcRenderer.send(\"Oni.started\", \"started\")\n    _initializePromise.resolve()\n}\n\nconst checkForUpdates = async (): Promise<void> => {\n    const AutoUpdate = await import(\"./Services/AutoUpdate\")\n    const { autoUpdater, constructFeedUrl } = AutoUpdate\n\n    const feedUrl = await constructFeedUrl(\"https://api.onivim.io/v1/update\")\n\n    autoUpdater.onUpdateAvailable.subscribe(() => Log.info(\"Update available.\"))\n    autoUpdater.onUpdateNotAvailable.subscribe(() => Log.info(\"Update not available.\"))\n\n    autoUpdater.checkForUpdates(feedUrl)\n}\n"
  },
  {
    "path": "browser/src/CSS.ts",
    "content": "/**\n * CSS.ts\n *\n * Entry point for loading all of Oni's CSS\n */\n\nexport const activate = () => {\n    require(\"./UI/components/common.less\") // tslint:disable-line no-var-requires\n    require(\"./overlay.less\") // tslint:disable-line\n\n    require(\"./Services/Menu/Menu.less\")\n    require(\"./UI/components/InstallHelp.less\")\n}\n"
  },
  {
    "path": "browser/src/Constants.ts",
    "content": "/**\n * Constants.ts\n */\n\n// Performance Constants\nexport namespace Delay {\n    export const INSTANT = 1\n    export const REAL_TIME = 10\n    export const NEAR_REAL_TIME = 50\n    export const NOT_REAL_TIME = 250\n}\n\nexport namespace Vim {\n    export const MAX_VALUE = 2147483647\n}\n"
  },
  {
    "path": "browser/src/Editor/BufferHighlights.ts",
    "content": "/**\n * BufferHighlights.ts\n *\n * Helpers to manage buffer highlight state\n */\n\nimport * as SyntaxHighlighting from \"./../Services/SyntaxHighlighting\"\n\nimport { NeovimInstance } from \"./../neovim\"\n\n// Line number to highlight src id, for clearing\nexport type BufferHighlightId = number\n\nexport interface IBufferHighlightsUpdater {\n    setHighlightsForLine(line: number, highlights: SyntaxHighlighting.HighlightInfo[]): void\n    clearHighlightsForLine(line: number): void\n}\n\n/**\n * Helper class to efficiently update\n * buffer highlights in a batch\n *\n * @name BufferHighlightsUpdater\n * @class\n */\nexport class BufferHighlightsUpdater implements IBufferHighlightsUpdater {\n    private _calls: any[] = []\n\n    constructor(\n        private _bufferId: number,\n        private _neovimInstance: NeovimInstance,\n        private _highlightId: BufferHighlightId,\n    ) {}\n\n    public async start(): Promise<void> {\n        if (!this._highlightId) {\n            this._highlightId = await this._neovimInstance.request<number>(\n                \"nvim_buf_add_highlight\",\n                [this._bufferId, 0, \"\", 0, 0, 0],\n            )\n        }\n    }\n\n    public setHighlightsForLine(\n        line: number,\n        highlights: SyntaxHighlighting.HighlightInfo[],\n    ): void {\n        this.clearHighlightsForLine(line)\n\n        if (!highlights || !highlights.length) {\n            return\n        }\n\n        const addHighlightCalls = highlights.map(hl => {\n            const highlightGroup = this._neovimInstance.tokenColorSynchronizer.getHighlightGroupForTokenColor(\n                hl.tokenColor,\n            )\n\n            return [\n                \"nvim_buf_add_highlight\",\n                [\n                    this._bufferId,\n                    this._highlightId,\n                    highlightGroup,\n                    hl.range.start.line,\n                    hl.range.start.character,\n                    hl.range.end.character,\n                ],\n            ]\n        })\n\n        this._calls = this._calls.concat(addHighlightCalls)\n    }\n    public clearHighlightsForLine(line: number): void {\n        this._calls.push([\n            \"nvim_buf_clear_highlight\",\n            [this._bufferId, this._highlightId, line, line + 1],\n        ])\n    }\n\n    public async apply(): Promise<BufferHighlightId> {\n        if (this._calls.length > 0) {\n            await this._neovimInstance.request<void>(\"nvim_call_atomic\", [this._calls])\n        }\n        return this._highlightId\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/BufferManager.ts",
    "content": "/**\n * BufferManager.ts\n *\n * Helpers to manage buffer state\n */\n\nimport * as os from \"os\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Observable } from \"rxjs/Observable\"\n\nimport \"rxjs/add/observable/defer\"\nimport \"rxjs/add/observable/from\"\nimport \"rxjs/add/operator/concatMap\"\n\nimport { Store } from \"redux\"\n\nimport * as detectIndent from \"detect-indent\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport {\n    BufferEventContext,\n    EventContext,\n    InactiveBufferContext,\n    NeovimInstance,\n} from \"./../neovim\"\nimport * as LanguageManager from \"./../Services/Language\"\nimport { PromiseQueue } from \"./../Services/Language/PromiseQueue\"\n\nimport {\n    BufferHighlightId,\n    BufferHighlightsUpdater,\n    IBufferHighlightsUpdater,\n} from \"./BufferHighlights\"\n\nimport * as Actions from \"./NeovimEditor/NeovimEditorActions\"\nimport * as State from \"./NeovimEditor/NeovimEditorStore\"\n\nimport * as Constants from \"./../Constants\"\nimport { TokenColor } from \"./../Services/TokenColors\"\n\nimport { IBufferLayer } from \"./NeovimEditor/BufferLayerManager\"\n\n/**\n * Candidate API methods\n */\nexport interface IBuffer extends Oni.Buffer {\n    tabstop: number\n    shiftwidth: number\n    comment: ICommentFormats\n\n    setLanguage(lang: string): Promise<void>\n    getLayerById<T>(id: string): T\n\n    getCursorPosition(): Promise<types.Position>\n    handleInput(key: string): boolean\n    detectIndentation(): Promise<BufferIndentationInfo>\n    setScratchBuffer(): Promise<void>\n}\n\ntype NvimError = [1, string]\n\ninterface ICommentFormats {\n    start: string\n    middle: string\n    end: string\n    defaults: string[]\n}\n\nconst isStringArray = (value: NvimError | string[]): value is string[] => {\n    if (value && Array.isArray(value)) {\n        return typeof value[0] === \"string\"\n    }\n    return false\n}\n\nexport type IndentationType = \"tab\" | \"space\"\n\nexport interface BufferIndentationInfo {\n    type: IndentationType\n\n    // If indentation is 'space', this is how\n    // many spaces are at a particular tabstop\n    amount: number\n\n    // String value for indentation\n    indent: string\n}\n\nconst getStringFromTypeAndAmount = (type: IndentationType, amount: number): string => {\n    if (type === \"tab\") {\n        return \"\\t\"\n    } else {\n        let str = \"\"\n        for (let i = 0; i < amount; i++) {\n            str += \" \"\n        }\n        return str\n    }\n}\n\nexport class Buffer implements IBuffer {\n    private _id: string\n    private _filePath: string\n    private _language: string\n    private _cursor: Oni.Cursor\n    private _cursorOffset: number\n    private _version: number\n    private _modified: boolean\n    private _lineCount: number\n    private _tabstop: number\n    private _shiftwidth: number\n    private _comment: ICommentFormats\n\n    private _bufferHighlightId: BufferHighlightId = null\n\n    private _promiseQueue = new PromiseQueue()\n\n    public get shiftwidth(): number {\n        return this._shiftwidth\n    }\n\n    public get tabstop(): number {\n        return this._tabstop\n    }\n\n    public get comment(): ICommentFormats {\n        return this._comment\n    }\n\n    public get filePath(): string {\n        return this._filePath\n    }\n\n    public get language(): string {\n        return this._language\n    }\n\n    public get lineCount(): number {\n        return this._lineCount\n    }\n\n    public get cursor(): Oni.Cursor {\n        return this._cursor\n    }\n\n    public get cursorOffset(): number {\n        return this._cursorOffset\n    }\n\n    public get version(): number {\n        return this._version\n    }\n\n    public get modified(): boolean {\n        return this._modified\n    }\n\n    public get id(): string {\n        return this._id\n    }\n\n    constructor(\n        private _neovimInstance: NeovimInstance,\n        private _actions: typeof Actions,\n        private _store: Store<State.IState>,\n        evt: EventContext,\n    ) {\n        this.updateFromEvent(evt)\n    }\n\n    public addLayer(layer: IBufferLayer): void {\n        this._actions.addBufferLayer(parseInt(this._id, 10), layer)\n    }\n\n    public getLayerById<T>(id: string): T | null {\n        return (\n            ((this._store\n                .getState()\n                .layers[parseInt(this._id, 10)].find(layer => layer.id === id) as any) as T) || null\n        )\n    }\n\n    public removeLayer(layer: IBufferLayer): void {\n        this._actions.removeBufferLayer(parseInt(this._id, 10), layer)\n    }\n\n    /**\n     * convertOffsetToLineColumn\n     */\n    public async convertOffsetToLineColumn(\n        cursorOffset = this._cursorOffset,\n    ): Promise<types.Position> {\n        const line: number = await this._neovimInstance.callFunction(\"byte2line\", [cursorOffset])\n        const countFromLine: number = await this._neovimInstance.callFunction(\"line2byte\", [line])\n        const column = cursorOffset - countFromLine\n        return types.Position.create(line - 1, column)\n    }\n\n    public async getCursorPosition(): Promise<types.Position> {\n        const pos = await this._neovimInstance.callFunction(\"getpos\", [\".\"])\n        const [, oneBasedLine, oneBasedColumn] = pos\n        return types.Position.create(oneBasedLine - 1, oneBasedColumn - 1)\n    }\n\n    public async getLines(start?: number, end?: number): Promise<string[]> {\n        if (typeof start !== \"number\") {\n            start = 0\n        }\n\n        if (typeof end !== \"number\") {\n            end = this._lineCount\n        }\n\n        if (end - start > 2500) {\n            Log.warn(\"getLines called with over 2500 lines, this may cause instability.\")\n        }\n\n        // Neovim does not error if it is unable to get lines instead it returns an array\n        // of type [1, \"an error message\"] **on Some occasions**, we only check the first on the assumption that\n        // that is where the number is placed by neovim\n        const lines = await this._neovimInstance.request<string[]>(\"nvim_buf_get_lines\", [\n            parseInt(this._id, 10),\n            start,\n            end,\n            false,\n        ])\n\n        if (isStringArray(lines)) {\n            return lines\n        }\n        return []\n    }\n\n    public async setLanguage(language: string): Promise<void> {\n        this._language = language\n        await this._neovimInstance.command(`setl ft=${language}`)\n    }\n\n    public async setScratchBuffer(): Promise<void> {\n        // set the open buffer to be a readonly throw away buffer, also add scrollbind\n        // may need a config option\n        const calls = [\n            [\"nvim_command\", [\"setlocal buftype=nofile\"]],\n            [\"nvim_command\", [\"setlocal bufhidden=hide\"]],\n            [\"nvim_command\", [\"setlocal noswapfile\"]],\n            [\"nvim_command\", [\"setlocal nobuflisted\"]],\n            [\"nvim_command\", [\"setlocal nomodifiable\"]],\n        ]\n\n        const [result, error] = await this._neovimInstance.request<any[] | NvimError>(\n            \"nvim_call_atomic\",\n            [calls],\n        )\n\n        if (typeof result === \"number\" && error) {\n            Log.info(`Failed to set scratch buffer due to ${error}`)\n        }\n        this._modified = false\n    }\n\n    public async detectIndentation(): Promise<BufferIndentationInfo> {\n        const bufferLines = await this.getLines(0, 1024)\n\n        const ret = detectIndent(bufferLines.join(\"\\n\"))\n\n        // We were able to infer tab settings from lines, so return\n        if (ret.type === \"tab\" || ret.type === \"space\") {\n            return ret\n        }\n\n        // Otherwise, we'll fall back to getting vim tab settings\n        const isSpaces = await this._neovimInstance.request<boolean>(\"nvim_get_option\", [\n            \"expandtab\",\n        ])\n        const tabSize = await this._neovimInstance.request<number>(\"nvim_get_option\", [\"tabstop\"])\n\n        const tabType = isSpaces ? \"space\" : \"tab\"\n        return {\n            amount: tabSize,\n            type: tabType,\n            indent: getStringFromTypeAndAmount(tabType, tabSize),\n        }\n    }\n\n    public async applyTextEdits(textEdits: types.TextEdit | types.TextEdit[]): Promise<void> {\n        const textEditsAsArray = textEdits instanceof Array ? textEdits : [textEdits]\n\n        const sortedEdits = LanguageManager.sortTextEdits(textEditsAsArray)\n\n        const deferredEdits = sortedEdits.map(te => {\n            return Observable.defer(async () => {\n                const range = te.range\n                Log.info(\"[Buffer] Applying edit\")\n\n                const characterStart = range.start.character\n                const lineStart = range.start.line\n                const lineEnd = range.end.line\n                const characterEnd = range.end.character\n\n                const calls = []\n\n                calls.push([\"nvim_command\", [\"silent! undojoin\"]])\n\n                if (lineStart === lineEnd) {\n                    const [lineContents] = await this.getLines(lineStart, lineStart + 1)\n                    const beginning = lineContents.substring(0, range.start.character)\n                    const end = lineContents.substring(range.end.character, lineContents.length)\n                    const newLine = beginning + te.newText + end\n\n                    const lines = newLine.split(os.EOL)\n\n                    calls.push([\n                        \"nvim_buf_set_lines\",\n                        [parseInt(this._id, 10), lineStart, lineStart + 1, false, lines],\n                    ])\n                } else if (characterEnd === 0 && characterStart === 0) {\n                    const lines = te.newText.split(os.EOL)\n                    calls.push([\n                        \"nvim_buf_set_lines\",\n                        [parseInt(this._id, 10), lineStart, lineEnd, false, lines],\n                    ])\n                } else {\n                    Log.warn(\"Multi-line mid character edits not currently supported\")\n                }\n\n                await this._neovimInstance.request(\"nvim_call_atomic\", [calls])\n            })\n        })\n\n        await Observable.from(deferredEdits)\n            .concatMap(de => de)\n            .toPromise()\n    }\n\n    public handleInput(key: string): boolean {\n        const state = this._store.getState()\n\n        const bufferLayers: IBufferLayer[] = state.layers[this._id]\n\n        if (!bufferLayers || !bufferLayers.length) {\n            return false\n        }\n\n        const layerShouldHandleInput = bufferLayers.reduce<boolean>(\n            (layerHandlerExists, currentLayer) => {\n                if (layerHandlerExists) {\n                    return true\n                }\n\n                if (!currentLayer || !currentLayer.handleInput) {\n                    return false\n                } else if (currentLayer.isActive && currentLayer.isActive()) {\n                    return currentLayer.handleInput(key)\n                }\n                return false\n            },\n            false,\n        )\n\n        return layerShouldHandleInput\n    }\n    public async updateHighlights(\n        tokenColors: TokenColor[],\n        updateFunction: (highlightsUpdater: IBufferHighlightsUpdater) => void,\n    ): Promise<void> {\n        this._promiseQueue.enqueuePromise(async () => {\n            const bufferId = parseInt(this._id, 10)\n            const bufferUpdater = new BufferHighlightsUpdater(\n                bufferId,\n                this._neovimInstance,\n                this._bufferHighlightId,\n            )\n            await this._neovimInstance.tokenColorSynchronizer.synchronizeTokenColors(tokenColors)\n            await bufferUpdater.start()\n\n            updateFunction(bufferUpdater)\n\n            this._bufferHighlightId = await bufferUpdater.apply()\n        })\n    }\n\n    public async setLines(start: number, end: number, lines: string[]): Promise<void> {\n        return this._neovimInstance.request<any>(\"nvim_buf_set_lines\", [\n            parseInt(this._id, 10),\n            start,\n            end,\n            false,\n            lines,\n        ])\n    }\n\n    public async setCursorPosition(row: number, column: number): Promise<void> {\n        await this._neovimInstance.eval(`setpos(\".\", [${this._id}, ${row + 1}, ${column + 1}, 0])`)\n    }\n\n    public async getSelectionRange(): Promise<types.Range | null> {\n        const startRange = await this._neovimInstance.callFunction(\"getpos\", [\"'<'\"])\n        const endRange = await this._neovimInstance.callFunction(\"getpos\", [\"'>\"])\n\n        const [, startLine, startColumn] = startRange\n        let [, endLine, endColumn] = endRange\n\n        if (startLine === 0 && startColumn === 0 && endLine === 0 && endColumn === 0) {\n            return null\n        }\n\n        if (endColumn === Constants.Vim.MAX_VALUE) {\n            endLine++\n            endColumn = 1\n        }\n\n        return types.Range.create(startLine - 1, startColumn - 1, endLine - 1, endColumn - 1)\n    }\n\n    public async getTokenAt(line: number, column: number): Promise<Oni.IToken> {\n        const result = await this.getLines(line, line + 1)\n\n        const tokenRegEx = LanguageManager.getInstance().getTokenRegex(this.language)\n\n        const getLastMatchingCharacter = (\n            lineContents: string,\n            character: number,\n            dir: number,\n            regex: RegExp,\n        ) => {\n            while (character > 0 && character < lineContents.length) {\n                if (!lineContents[character].match(regex)) {\n                    return character - dir\n                }\n\n                character += dir\n            }\n\n            return character\n        }\n\n        const getToken = (lineContents: string, character: number): Oni.IToken => {\n            if (!lineContents || !character) {\n                return null\n            }\n\n            const tokenStart = getLastMatchingCharacter(lineContents, character, -1, tokenRegEx)\n            const tokenEnd = getLastMatchingCharacter(lineContents, character, 1, tokenRegEx)\n\n            const range = types.Range.create(line, tokenStart, line, tokenEnd)\n            const tokenName = lineContents.substring(tokenStart, tokenEnd + 1)\n\n            return {\n                tokenName,\n                range,\n            }\n        }\n\n        return getToken(result[0], column)\n    }\n\n    public updateFromEvent(evt: EventContext): void {\n        this._id = evt.bufferNumber.toString()\n        this._filePath = evt.bufferFullPath\n        this._language = evt.filetype\n        this._version = evt.version\n        this._modified = evt.modified\n        this._lineCount = evt.bufferTotalLines\n        this._cursorOffset = evt.byte\n        this._tabstop = evt.tabstop\n        this._shiftwidth = evt.shiftwidth\n        this._comment = this.formatCommentOption(evt.comments)\n\n        this._cursor = {\n            line: evt.line - 1,\n            column: evt.column - 1,\n        }\n    }\n\n    public formatCommentOption(comments: string): ICommentFormats {\n        if (!comments) {\n            return null\n        }\n        try {\n            const commentsArray = comments.split(\",\")\n            const commentFormats = commentsArray.reduce<ICommentFormats>(\n                (acc, str) => {\n                    const [flag, character] = str.split(\":\")\n                    switch (true) {\n                        case flag.includes(\"s\"):\n                            acc.start = character\n                            return acc\n                        case flag.includes(\"m\"):\n                            acc.middle = character\n                            return acc\n                        case flag.includes(\"e\"):\n                            acc.end = character\n                            return acc\n                        default:\n                            acc.defaults.push(character)\n                            return acc\n                    }\n                },\n                {\n                    start: null,\n                    middle: null,\n                    end: null,\n                    defaults: [],\n                },\n            )\n\n            return commentFormats\n        } catch (e) {\n            Log.warn(`Error formatting neovim comment options due to ${e.message}`)\n            return null\n        }\n    }\n}\n\n// Helper for managing buffer state\nexport class BufferManager {\n    private _idToBuffer: { [id: string]: Buffer } = {}\n    private _filePathToId: { [filePath: string]: string } = {}\n    private _bufferList: { [id: string]: InactiveBuffer } = {}\n\n    constructor(\n        private _neovimInstance: NeovimInstance,\n        private _actions: typeof Actions,\n        private _store: Store<State.IState>,\n    ) {}\n\n    public updateBufferFromEvent(evt: EventContext): Buffer {\n        const id = evt.bufferNumber.toString()\n        const currentBuffer = this.getBufferById(id)\n\n        if (evt.bufferFullPath) {\n            this._filePathToId[evt.bufferFullPath] = id\n        }\n\n        if (currentBuffer) {\n            currentBuffer.updateFromEvent(evt)\n        } else {\n            const buf = new Buffer(this._neovimInstance, this._actions, this._store, evt)\n            this._idToBuffer[id] = buf\n        }\n\n        return this._idToBuffer[id]\n    }\n\n    public populateBufferList(buffers: BufferEventContext): void {\n        const bufferlist = buffers.existingBuffers.reduce((list, buffer) => {\n            const id = `${buffer.bufferNumber}`\n            if (buffer.bufferFullPath) {\n                this._filePathToId[buffer.bufferFullPath] = id\n                list[id] = new InactiveBuffer(buffer)\n            }\n            return list\n        }, {})\n        const currentId = buffers.current.bufferNumber.toString()\n        const current = this.getBufferById(currentId)\n        this._bufferList = { ...bufferlist, [currentId]: current }\n    }\n\n    public getBufferById(id: string): Buffer {\n        return this._idToBuffer[id]\n    }\n\n    public getBuffers(): Array<Buffer | InactiveBuffer> {\n        return Object.values(this._bufferList)\n    }\n}\n\nexport class InactiveBuffer implements Oni.InactiveBuffer {\n    private _id: string\n    private _filePath: string\n    private _language: string\n    private _version: number\n    private _modified: boolean\n    private _lineCount: number\n\n    public get id(): string {\n        return this._id\n    }\n\n    public get filePath(): string {\n        return this._filePath\n    }\n    public get language(): string {\n        return this._language\n    }\n    public get version(): number {\n        return this._version\n    }\n    public get modified(): boolean {\n        return this._modified\n    }\n    public get lineCount(): number {\n        return this._lineCount\n    }\n\n    constructor(inactiveBuffer: InactiveBufferContext) {\n        this._id = `${inactiveBuffer.bufferNumber}`\n        this._filePath = inactiveBuffer.bufferFullPath\n        this._language = inactiveBuffer.filetype\n        this._version = inactiveBuffer.version || null\n        this._modified = inactiveBuffer.modified || false\n        this._lineCount = null\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/Editor.ts",
    "content": "/**\n * Interface that describes an Editor -\n * an editor handles rendering and input\n * for a specific window.\n */\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Disposable } from \"./../Utility\"\n\n/**\n * Base class for Editor implementations\n */\nexport abstract class Editor extends Disposable implements Oni.Editor {\n    private _currentMode: string\n    private _onBufferEnterEvent = new Event<Oni.EditorBufferEventArgs>()\n    private _onBufferLeaveEvent = new Event<Oni.EditorBufferEventArgs>()\n    private _onBufferChangedEvent = new Event<Oni.EditorBufferChangedEventArgs>()\n    private _onBufferSavedEvent = new Event<Oni.EditorBufferEventArgs>()\n    private _onBufferScrolledEvent = new Event<Oni.EditorBufferScrolledEventArgs>()\n    private _onCursorMoved = new Event<Oni.Cursor>()\n    private _onModeChangedEvent = new Event<Oni.Vim.Mode>()\n\n    public get mode(): string {\n        return this._currentMode\n    }\n\n    public get activeBuffer(): Oni.Buffer {\n        return null\n    }\n\n    public get onCursorMoved(): IEvent<Oni.Cursor> {\n        return this._onCursorMoved\n    }\n\n    public abstract init(filesToOpen: string[]): void\n\n    // Events\n\n    public get onModeChanged(): IEvent<Oni.Vim.Mode> {\n        return this._onModeChangedEvent\n    }\n\n    public get onBufferEnter(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._onBufferEnterEvent\n    }\n\n    public get onBufferLeave(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._onBufferLeaveEvent\n    }\n\n    public get onBufferChanged(): IEvent<Oni.EditorBufferChangedEventArgs> {\n        return this._onBufferChangedEvent\n    }\n\n    public get onBufferSaved(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._onBufferSavedEvent\n    }\n\n    public get onBufferScrolled(): IEvent<Oni.EditorBufferScrolledEventArgs> {\n        return this._onBufferScrolledEvent\n    }\n\n    public getBuffers(): Array<Oni.Buffer | Oni.InactiveBuffer> {\n        return []\n    }\n\n    public /* virtual */ openFile(\n        filePath: string,\n        openOptions: Oni.FileOpenOptions = Oni.DefaultFileOpenOptions,\n    ): Promise<Oni.Buffer> {\n        return Promise.reject(\"Not implemented\")\n    }\n\n    public async blockInput(\n        inputFunction: (input: Oni.InputCallbackFunction) => Promise<void>,\n    ): Promise<void> {\n        return Promise.reject(\"Not implemented\")\n    }\n\n    public setTextOptions(options: Oni.EditorTextOptions): Promise<void> {\n        return Promise.reject(\"Not implemented\")\n    }\n\n    public abstract render(): JSX.Element\n\n    public abstract setSelection(selectionRange: types.Range): Promise<void>\n\n    protected setMode(mode: Oni.Vim.Mode): void {\n        if (mode !== this._currentMode) {\n            this._currentMode = mode\n            this._onModeChangedEvent.dispatch(mode)\n        }\n    }\n\n    protected notifyCursorMoved(cursor: Oni.Cursor): void {\n        this._onCursorMoved.dispatch(cursor)\n    }\n\n    protected notifyBufferChanged(bufferChangeEvent: Oni.EditorBufferChangedEventArgs): void {\n        this._onBufferChangedEvent.dispatch(bufferChangeEvent)\n    }\n\n    protected notifyBufferEnter(bufferEvent: Oni.EditorBufferEventArgs): void {\n        this._onBufferEnterEvent.dispatch(bufferEvent)\n    }\n\n    protected notifyBufferLeave(bufferEvent: Oni.EditorBufferEventArgs): void {\n        this._onBufferLeaveEvent.dispatch(bufferEvent)\n    }\n\n    protected notifyBufferSaved(bufferEvent: Oni.EditorBufferEventArgs): void {\n        this._onBufferSavedEvent.dispatch(bufferEvent)\n    }\n\n    protected notifyBufferScrolled(bufferScrollEvent: Oni.EditorBufferScrolledEventArgs): void {\n        this._onBufferScrolledEvent.dispatch(bufferScrollEvent)\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/BufferLayerManager.ts",
    "content": "/**\n * BufferLayerManager.ts\n *\n * BufferLayerManager tracks the lifecycle of 'buffer layers'\n */\n\nimport * as Oni from \"oni-api\"\n\nexport type BufferLayerFactory = (buf: Oni.Buffer) => Oni.BufferLayer\nexport type BufferFilter = (buf: Oni.Buffer) => boolean\n\nexport interface IBufferLayer extends Oni.BufferLayer {\n    handleInput?: (key: string) => boolean\n    isActive?: () => boolean\n}\n\nexport const createBufferFilterFromLanguage = (language: string) => (buf: Oni.Buffer): boolean => {\n    if (!language || language === \"*\") {\n        return true\n    } else {\n        return buf.language === language\n    }\n}\n\nexport interface BufferLayerInfo {\n    filter: BufferFilter\n    layerFactory: BufferLayerFactory\n}\n\nexport class BufferLayerManager {\n    private _layers: BufferLayerInfo[] = []\n\n    private _buffers: Oni.Buffer[] = []\n    public addBufferLayer(\n        filterOrLanguage: BufferFilter | string,\n        layerFactory: BufferLayerFactory,\n    ) {\n        const filter: BufferFilter =\n            typeof filterOrLanguage === \"string\"\n                ? createBufferFilterFromLanguage(filterOrLanguage)\n                : filterOrLanguage\n\n        this._layers.push({\n            filter,\n            layerFactory,\n        })\n\n        this._buffers.forEach(buf => {\n            if (filter(buf)) {\n                buf.addLayer(layerFactory(buf))\n            }\n        })\n    }\n\n    public notifyBufferEnter(buf: Oni.Buffer): void {\n        if (this._buffers.indexOf(buf) === -1) {\n            this._buffers.push(buf)\n\n            this._layers.forEach(layerInfo => {\n                if (layerInfo.filter(buf)) {\n                    buf.addLayer(layerInfo.layerFactory(buf))\n                }\n            })\n        }\n    }\n\n    public notifyBufferFileTypeChanged(buf: Oni.Buffer): void {\n        this._buffers = this._buffers.filter(b => b.id !== buf.id)\n        this.notifyBufferEnter(buf)\n    }\n}\n\nconst getInstance = (() => {\n    const instance = new BufferLayerManager()\n    return () => instance\n})()\n\nexport default getInstance\n\nexport const wrapReactComponentWithLayer = (\n    id: string,\n    component: JSX.Element,\n): Oni.BufferLayer => {\n    return {\n        id,\n        render: (context: Oni.BufferLayerRenderContext) => (context.isActive ? component : null),\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/CompletionMenu.ts",
    "content": "/**\n * CompletionMenu.ts\n *\n * This is the completion menu that integrates with the completion providers\n * (which is primarily language server right now)\n * It's really just glue between the ContextMenu and Completion store.\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { getDocumentationText } from \"../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { ContextMenu } from \"./../../Services/ContextMenu\"\n\nimport * as CompletionUtility from \"./../../Services/Completion/CompletionUtility\"\n\nexport class CompletionMenu {\n    private _onItemFocusedEvent: Event<types.CompletionItem> = new Event<types.CompletionItem>()\n    private _onItemSelectedEvent: Event<types.CompletionItem> = new Event<types.CompletionItem>()\n\n    public get onItemFocused(): IEvent<types.CompletionItem> {\n        return this._onItemFocusedEvent\n    }\n\n    public get onItemSelected(): IEvent<types.CompletionItem> {\n        return this._onItemSelectedEvent\n    }\n\n    constructor(private _contextMenu: ContextMenu) {\n        this._contextMenu.onSelectedItemChanged.subscribe(item =>\n            this._onItemFocusedEvent.dispatch(item.rawCompletion),\n        )\n        this._contextMenu.onItemSelected.subscribe(item =>\n            this._onItemSelectedEvent.dispatch(item.rawCompletion),\n        )\n    }\n\n    public show(options: types.CompletionItem[], filterText: string): void {\n        const menuOptions = options.map(_convertCompletionForContextMenu)\n\n        if (this._contextMenu.isOpen()) {\n            this._contextMenu.setItems(menuOptions)\n            this._contextMenu.setFilter(filterText)\n        } else {\n            this._contextMenu.show(menuOptions, filterText)\n        }\n    }\n\n    public hide(): void {\n        this._contextMenu.hide()\n    }\n}\n\n// TODO: Should this be moved to another level? Like over to the menu renderer?\n// It'd be nice if this layer only cared about `types.CompletionItem` and didn't\n// have to worry about presentational aspects..\nconst _convertCompletionForContextMenu = (completion: types.CompletionItem): any => ({\n    label: completion.label,\n    detail: completion.detail,\n    documentation: getCompletionDocumentation(completion),\n    icon: CompletionUtility.convertKindToIconName(completion.kind),\n    rawCompletion: completion,\n})\n\nconst getCompletionDocumentation = (item: types.CompletionItem): string | null => {\n    if (item.documentation) {\n        return getDocumentationText(item.documentation)\n    } else if (item.data && item.data.documentation) {\n        return item.data.documentation\n    } else {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/Definition.ts",
    "content": "/**\n * Definition.ts\n */\n\nimport { Store } from \"redux\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport * as State from \"./NeovimEditorStore\"\n\nexport enum OpenType {\n    NewTab = 0,\n    SplitVertical = 1,\n    SplitHorizontal = 2,\n}\n\nexport class Definition {\n    constructor(private _editor: Oni.Editor, private _store: Store<State.IState>) {}\n\n    public async gotoDefinitionUnderCursor(openOptions?: Oni.FileOpenOptions): Promise<void> {\n        const activeDefinition = this._store.getState().definition\n\n        if (!activeDefinition) {\n            return\n        }\n\n        const { uri, range } = activeDefinition.definitionLocation\n\n        const line = range.start.line\n        const column = range.start.character\n\n        await this.gotoPositionInUri(uri, line, column, openOptions)\n    }\n\n    public async gotoPositionInUri(\n        uri: string,\n        line: number,\n        column: number,\n        openOptions?: Oni.FileOpenOptions,\n    ): Promise<void> {\n        const filePath = Helpers.unwrapFileUriPath(uri)\n\n        const activeEditor = this._editor\n\n        await this._editor.openFile(filePath, openOptions)\n        await activeEditor.neovim.command(`cal cursor(${line + 1}, ${column + 1})`)\n        await activeEditor.neovim.command(\"norm zz\")\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/FileDropHandler.tsx",
    "content": "import * as React from \"react\"\n\ntype SetRef = (elem: HTMLElement) => void\n\ninterface IFileDropHandler {\n    handleFiles: (files: FileList) => void\n    children: (args: { setRef: SetRef }) => React.ReactElement<{ setRef: SetRef }>\n}\n\ntype DragTypeName = \"ondragover\" | \"ondragleave\" | \"ondragenter\"\n\n/**\n * Gets a target element via a callback ref and attaches a file drop event listener callback\n * N.B. the element cannot be obscured as this will prevent event transmission\n * @name FileDropHandler\n * @function\n *\n * @extends {React}\n */\nexport default class FileDropHandler extends React.Component<IFileDropHandler> {\n    private _target: HTMLElement\n\n    public componentDidMount() {\n        this.addDropHandler()\n    }\n\n    public setRef = (element: HTMLElement) => {\n        this._target = element\n    }\n\n    public addDropHandler() {\n        if (!this._target) {\n            return\n        }\n\n        const dragTypes = [\"ondragenter\", \"ondragover\", \"ondragleave\"]\n\n        dragTypes.map((event: DragTypeName) => {\n            if (this._target[event]) {\n                this._target[event] = ev => {\n                    ev.preventDefault()\n                    ev.stopPropagation()\n                }\n            }\n        })\n\n        this._target.ondrop = async ev => {\n            const { files } = ev.dataTransfer\n\n            if (files.length) {\n                await this.props.handleFiles(files)\n            }\n            ev.preventDefault()\n        }\n    }\n\n    public render() {\n        return this.props.children({ setRef: this.setRef })\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/HoverRenderer.tsx",
    "content": "/**\n * Hover.tsx\n */\n\nimport * as Oni from \"oni-api\"\nimport * as os from \"os\"\nimport * as React from \"react\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport getTokens from \"./../../Services/SyntaxHighlighting/TokenGenerator\"\nimport styled, { enableMouse } from \"./../../UI/components/common\"\nimport { ErrorInfo } from \"./../../UI/components/ErrorInfo\"\nimport { QuickInfoElement } from \"./../../UI/components/QuickInfo\"\nimport QuickInfoWithTheme from \"./../../UI/components/QuickInfoContainer\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { Configuration } from \"./../../Services/Configuration\"\nimport { convertMarkdown } from \"./markdown\"\n\nimport { IToolTipsProvider } from \"./ToolTipsProvider\"\n\nconst HoverToolTipId = \"hover-tool-tip\"\n\nconst HoverRendererContainer = styled.div`\n    user-select: none;\n    cursor: default;\n    ${enableMouse};\n`\n\nexport class HoverRenderer {\n    constructor(\n        private _editor: Oni.Editor,\n        private _configuration: Configuration,\n        private _toolTipsProvider: IToolTipsProvider,\n    ) {}\n\n    public async showQuickInfo(\n        x: number,\n        y: number,\n        hover: types.Hover,\n        errors: types.Diagnostic[],\n    ): Promise<void> {\n        const elem = await this._renderQuickInfoElement(hover, errors)\n\n        if (!elem) {\n            return\n        }\n\n        this._toolTipsProvider.showToolTip(HoverToolTipId, elem, {\n            position: { pixelX: x, pixelY: y },\n            openDirection: 1,\n            padding: \"0px\",\n        })\n    }\n\n    public hideQuickInfo(): void {\n        this._toolTipsProvider.hideToolTip(HoverToolTipId)\n    }\n\n    private async _renderQuickInfoElement(\n        hover: types.Hover,\n        errors: types.Diagnostic[],\n    ): Promise<JSX.Element> {\n        const titleAndContents = await getTitleAndContents(hover)\n        const showDebugScope = this._configuration.getValue(\n            \"editor.textMateHighlighting.debugScopes\",\n        )\n\n        const errorsExist = Boolean(errors && errors.length)\n        const contentExists = Boolean(errorsExist || titleAndContents || showDebugScope)\n\n        return (\n            contentExists && (\n                <HoverRendererContainer>\n                    <QuickInfoElement>\n                        <div className=\"container horizontal center\">\n                            <div className=\"container full\">\n                                <ErrorElement\n                                    isVisible={errorsExist}\n                                    errors={errors}\n                                    hasQuickInfo={!!titleAndContents}\n                                />\n                                <QuickInfoWithTheme\n                                    isVisible={!!titleAndContents}\n                                    titleAndContents={titleAndContents}\n                                />\n                                {showDebugScope && this._getDebugScopesElement()}\n                            </div>\n                        </div>\n                    </QuickInfoElement>\n                </HoverRendererContainer>\n            )\n        )\n    }\n\n    private _getDebugScopesElement(): JSX.Element {\n        const editor: any = this._editor\n\n        if (!editor || !editor.syntaxHighlighter) {\n            return null\n        }\n\n        const cursor = editor.activeBuffer.cursor\n        const scopeInfo = editor.syntaxHighlighter.getHighlightTokenAt(editor.activeBuffer.id, {\n            line: cursor.line,\n            character: cursor.column,\n        })\n\n        if (!scopeInfo || !scopeInfo.scopes) {\n            return null\n        }\n\n        const items = scopeInfo.scopes.map((si: string) => <li key={si}>{si}</li>)\n        return (\n            <div\n                className=\"quick-info-debug-scopes\"\n                key=\"quickInfo.debugScopes\"\n                style={{ margin: \"16px\" }}\n            >\n                <div>DEBUG: TextMate Scopes:</div>\n                <ul style={{ paddingBlockStart: \"20px\" }}>{items}</ul>\n            </div>\n        )\n    }\n}\n\nconst html = (str: string) => ({ __html: str })\n\ninterface ErrorElementProps {\n    errors: types.Diagnostic[]\n    hasQuickInfo: boolean\n    isVisible: boolean\n}\n\nconst ErrorElement = ({ isVisible, errors, hasQuickInfo }: ErrorElementProps) => {\n    return (\n        isVisible && (\n            <ErrorInfo errors={errors} hasQuickInfo={hasQuickInfo} key=\"quickInfo.errorInfo\" />\n        )\n    )\n}\n\nconst getTitleAndContents = async (result: types.Hover) => {\n    if (!result || !result.contents) {\n        return null\n    }\n\n    const contents = Helpers.getTextFromContents(result.contents)\n\n    if (!contents.length) {\n        return null\n    }\n\n    const [{ value: titleContent, language }, ...remaining] = contents\n\n    if (!titleContent) {\n        return null\n    }\n\n    const remainder = remaining.map(r => r.value)\n    const [hasRemainder] = remainder\n\n    if (!hasRemainder) {\n        const tokensPerLine = await getTokens({ language, line: titleContent })\n\n        return {\n            title: html(convertMarkdown({ markdown: titleContent, tokens: tokensPerLine })),\n            description: null,\n        }\n    } else {\n        const descriptionContent = remainder.join(os.EOL)\n\n        const tokensPerLine = await getTokens({ language, line: titleContent })\n\n        return {\n            title: html(convertMarkdown({ markdown: titleContent, tokens: tokensPerLine })),\n            description: html(\n                convertMarkdown({\n                    markdown: descriptionContent,\n                    type: \"documentation\",\n                }),\n            ),\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimActiveWindow.tsx",
    "content": "/**\n * ActiveWindow.tsx\n *\n * Helper component that is always sized and positioned around the currently\n * active window in Neovim.\n */\n\nimport * as React from \"react\"\n\nexport interface IActiveWindowProps {\n    pixelX: number\n    pixelY: number\n    pixelWidth: number\n    pixelHeight: number\n}\n\nexport class NeovimActiveWindow extends React.PureComponent<IActiveWindowProps, {}> {\n    public render(): JSX.Element {\n        const px = (str: number): string => `${str}px`\n\n        const style: React.CSSProperties = {\n            position: \"absolute\",\n            left: px(this.props.pixelX),\n            top: px(this.props.pixelY),\n            width: px(this.props.pixelWidth),\n            height: px(this.props.pixelHeight),\n            overflowY: \"hidden\",\n            overflowX: \"hidden\",\n        }\n\n        return <div style={style}>{this.props.children}</div>\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimBufferLayersView.tsx",
    "content": "/**\n * NeovimLayersView.tsx\n *\n * Renders layers above vim windows\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport { createSelector } from \"reselect\"\n\nimport * as Oni from \"oni-api\"\n\nimport { NeovimActiveWindow } from \"./NeovimActiveWindow\"\n\nimport * as State from \"./NeovimEditorStore\"\n\nimport styled, { StackLayer } from \"../../UI/components/common\"\n\nexport interface NeovimBufferLayersViewProps {\n    activeWindowId: number\n    windows: State.IWindow[]\n    layers: State.Layers\n    fontPixelWidth: number\n    fontPixelHeight: number\n}\n\nconst InnerLayer = styled.div`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n    overflow: hidden;\n`\n\nexport interface LayerContextWithCursor extends Oni.BufferLayerRenderContext {\n    cursorLine: number\n    cursorColumn: number\n}\n\nexport class NeovimBufferLayersView extends React.PureComponent<NeovimBufferLayersViewProps, {}> {\n    public render(): JSX.Element {\n        const containers = this.props.windows.map(windowState => {\n            const layers: Oni.BufferLayer[] = this.props.layers[windowState.bufferId] || []\n\n            const layerContext: LayerContextWithCursor = {\n                isActive: windowState.windowId === this.props.activeWindowId,\n                windowId: windowState.windowId,\n                fontPixelWidth: this.props.fontPixelWidth,\n                fontPixelHeight: this.props.fontPixelHeight,\n                bufferToScreen: windowState.bufferToScreen,\n                screenToPixel: windowState.screenToPixel,\n                bufferToPixel: windowState.bufferToPixel,\n                dimensions: windowState.dimensions,\n                visibleLines: windowState.visibleLines,\n                topBufferLine: windowState.topBufferLine,\n                bottomBufferLine: windowState.bottomBufferLine,\n                cursorColumn: windowState.column,\n                cursorLine: windowState.line,\n            }\n\n            const layerElements = layers.map(layer => {\n                return (\n                    <InnerLayer key={`${layer.id}.${windowState.windowId}.${windowState.bufferId}`}>\n                        {layer.render(layerContext)}\n                    </InnerLayer>\n                )\n            })\n\n            const dimensions = getWindowPixelDimensions(windowState)\n\n            return (\n                <NeovimActiveWindow {...dimensions} key={windowState.windowId.toString()}>\n                    {layerElements}\n                </NeovimActiveWindow>\n            )\n        })\n\n        return <StackLayer>{containers}</StackLayer>\n    }\n}\n\nconst EmptySize = {\n    pixelX: -1,\n    pixelY: -1,\n    pixelWidth: 0,\n    pixelHeight: 0,\n}\n\nconst getWindowPixelDimensions = (win: State.IWindow) => {\n    if (!win || !win.screenToPixel) {\n        return EmptySize\n    }\n\n    const start = win.screenToPixel({\n        screenX: win.dimensions.x,\n        screenY: win.dimensions.y,\n    })\n\n    const size = win.screenToPixel({\n        screenX: win.dimensions.width,\n        screenY: win.dimensions.height,\n    })\n\n    return {\n        pixelX: start.pixelX,\n        pixelY: start.pixelY - 1,\n        pixelWidth: size.pixelX,\n        pixelHeight: size.pixelY + 2,\n    }\n}\n\nconst EmptyState: NeovimBufferLayersViewProps = {\n    activeWindowId: -1,\n    layers: {},\n    windows: [],\n    fontPixelHeight: -1,\n    fontPixelWidth: -1,\n}\n\nconst getActiveVimTabPage = (state: State.IState) => state.activeVimTabPage\nconst getWindowState = (state: State.IState) => state.windowState\n\nconst windowSelector = createSelector(\n    [getActiveVimTabPage, getWindowState],\n    (tabPage: State.IVimTabPage, windowState: State.IWindowState) => {\n        const windows = tabPage.windowIds.map(windowId => {\n            return windowState.windows[windowId]\n        })\n\n        return windows.sort((a, b) => a.windowId - b.windowId)\n    },\n)\n\nconst mapStateToProps = (state: State.IState): NeovimBufferLayersViewProps => {\n    if (!state.activeVimTabPage) {\n        return EmptyState\n    }\n\n    const windows = windowSelector(state)\n\n    return {\n        activeWindowId: state.windowState.activeWindow,\n        windows,\n        layers: state.layers,\n        fontPixelWidth: state.fontPixelWidth,\n        fontPixelHeight: state.fontPixelHeight,\n    }\n}\n\nexport const NeovimBufferLayers = connect(mapStateToProps)(NeovimBufferLayersView)\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditor.tsx",
    "content": "/**\n * NeovimEditor.ts\n *\n * Editor implementation for Neovim\n */\n\nimport * as os from \"os\"\nimport * as React from \"react\"\n\nimport \"rxjs/add/observable/defer\"\nimport \"rxjs/add/observable/merge\"\nimport \"rxjs/add/operator/map\"\nimport \"rxjs/add/operator/mergeMap\"\nimport { Observable } from \"rxjs/Observable\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Provider } from \"react-redux\"\nimport { bindActionCreators, Store } from \"redux\"\n\nimport { clipboard, ipcRenderer } from \"electron\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { addDefaultUnitIfNeeded } from \"./../../Font\"\nimport {\n    BufferEventContext,\n    EventContext,\n    INeovimStartOptions,\n    NeovimInstance,\n    NeovimScreen,\n    NeovimWindowManager,\n    ScreenWithPredictions,\n} from \"./../../neovim\"\nimport { INeovimRenderer } from \"./../../Renderer\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { IColors } from \"./../../Services/Colors\"\nimport { commandManager } from \"./../../Services/CommandManager\"\nimport { Completion, CompletionProviders } from \"./../../Services/Completion\"\nimport { Configuration, IConfigurationValues } from \"./../../Services/Configuration\"\nimport { IDiagnosticsDataSource } from \"./../../Services/Diagnostics\"\nimport { Overlay, OverlayManager } from \"./../../Services/Overlay\"\nimport { ISession } from \"./../../Services/Sessions\"\nimport { SnippetManager } from \"./../../Services/Snippets\"\nimport { TokenColors } from \"./../../Services/TokenColors\"\n\nimport * as Shell from \"./../../UI/Shell\"\n\nimport {\n    addInsertModeLanguageFunctionality,\n    LanguageEditorIntegration,\n    LanguageManager,\n} from \"./../../Services/Language\"\n\nimport {\n    ISyntaxHighlighter,\n    NullSyntaxHighlighter,\n    SyntaxHighlighter,\n} from \"./../../Services/SyntaxHighlighting\"\n\nimport { MenuManager } from \"./../../Services/Menu\"\nimport { IThemeMetadata, ThemeManager } from \"./../../Services/Themes\"\nimport { TypingPredictionManager } from \"./../../Services/TypingPredictionManager\"\nimport { Workspace } from \"./../../Services/Workspace\"\n\nimport { Editor } from \"./../Editor\"\n\nimport { BufferManager } from \"./../BufferManager\"\nimport { CompletionMenu } from \"./CompletionMenu\"\nimport { HoverRenderer } from \"./HoverRenderer\"\nimport { NeovimPopupMenu } from \"./NeovimPopupMenu\"\nimport NeovimSurface from \"./NeovimSurface\"\n\nimport { ContextMenuManager } from \"./../../Services/ContextMenu\"\n\nimport { asObservable, normalizePath, sleep } from \"./../../Utility\"\n\nimport * as VimConfigurationSynchronizer from \"./../../Services/VimConfigurationSynchronizer\"\n\nimport getLayerManagerInstance from \"./BufferLayerManager\"\nimport { Definition } from \"./Definition\"\nimport * as ActionCreators from \"./NeovimEditorActions\"\nimport { NeovimEditorCommands } from \"./NeovimEditorCommands\"\nimport { createStore, IState, ITab } from \"./NeovimEditorStore\"\nimport { Rename } from \"./Rename\"\nimport { Symbols } from \"./Symbols\"\nimport { IToolTipsProvider, NeovimEditorToolTipsProvider } from \"./ToolTipsProvider\"\n\nimport CommandLine from \"./../../UI/components/CommandLine\"\nimport ExternalMenus from \"./../../UI/components/ExternalMenus\"\nimport WildMenu from \"./../../UI/components/WildMenu\"\n\nimport { CanvasRenderer, WebGLRenderer } from \"../../Renderer\"\nimport { getInstance as getNotificationsInstance } from \"./../../Services/Notifications\"\n\ntype NeovimError = [number, string]\n\nexport class NeovimEditor extends Editor implements Oni.Editor {\n    private _bufferManager: BufferManager\n    private _neovimInstance: NeovimInstance\n    private _renderer: INeovimRenderer\n    private _screen: NeovimScreen\n    private _completionMenu: CompletionMenu\n    private _contextMenuManager: ContextMenuManager\n    private _popupMenu: NeovimPopupMenu\n    private _errorInitializing: boolean = false\n\n    private _store: Store<IState>\n    private _actions: typeof ActionCreators\n\n    private _pendingAnimationFrame: boolean = false\n\n    private _onEnterEvent: Event<void> = new Event<void>()\n\n    private _modeChanged$: Observable<Oni.Vim.Mode>\n    private _cursorMoved$: Observable<Oni.Cursor>\n    private _cursorMovedI$: Observable<Oni.Cursor>\n    private _onScroll$: Observable<Oni.EditorBufferScrolledEventArgs>\n\n    private _hasLoaded: boolean = false\n\n    private _windowManager: NeovimWindowManager\n\n    private _currentColorScheme: string = \"\"\n    private _currentBackground: string = \"\"\n    private _isFirstRender: boolean = true\n\n    private _lastBufferId: string = null\n\n    private _typingPredictionManager: TypingPredictionManager = new TypingPredictionManager()\n    private _syntaxHighlighter: ISyntaxHighlighter\n    private _languageIntegration: LanguageEditorIntegration\n    private _completion: Completion\n    private _hoverRenderer: HoverRenderer\n    private _rename: Rename = null\n    private _symbols: Symbols = null\n    private _definition: Definition = null\n    private _toolTipsProvider: IToolTipsProvider\n    private _commands: NeovimEditorCommands\n    private _externalMenuOverlay: Overlay\n    private _bufferLayerManager = getLayerManagerInstance()\n    private _screenWithPredictions: ScreenWithPredictions\n\n    private _onShowWelcomeScreen = new Event<void>()\n    private _onNeovimQuit: Event<void> = new Event<void>()\n\n    private _autoFocus: boolean = true\n\n    public get onNeovimQuit(): IEvent<void> {\n        return this._onNeovimQuit\n    }\n\n    public get onShowWelcomeScreen() {\n        return this._onShowWelcomeScreen\n    }\n\n    public get /* override */ activeBuffer(): Oni.Buffer {\n        return this._bufferManager.getBufferById(this._lastBufferId)\n    }\n\n    // Capabilities\n    public get neovim(): Oni.NeovimEditorCapability {\n        return this._neovimInstance\n    }\n\n    public get bufferLayers() {\n        return this._bufferLayerManager\n    }\n\n    /**\n     * Gets whether or not the editor should autoFocus,\n     * meaning, grab focus on first mount\n     */\n    public get autoFocus(): boolean {\n        return this._autoFocus\n    }\n    public set autoFocus(val: boolean) {\n        this._autoFocus = val\n    }\n\n    public get syntaxHighlighter(): ISyntaxHighlighter {\n        return this._syntaxHighlighter\n    }\n\n    constructor(\n        private _colors: IColors,\n        private _completionProviders: CompletionProviders,\n        private _configuration: Configuration,\n        private _diagnostics: IDiagnosticsDataSource,\n        private _languageManager: LanguageManager,\n        private _menuManager: MenuManager,\n        private _overlayManager: OverlayManager,\n        private _pluginManager: PluginManager,\n        private _snippetManager: SnippetManager,\n        private _themeManager: ThemeManager,\n        private _tokenColors: TokenColors,\n        private _workspace: Workspace,\n    ) {\n        super()\n\n        this._store = createStore()\n        this._actions = bindActionCreators(ActionCreators as any, this._store.dispatch)\n        this._toolTipsProvider = new NeovimEditorToolTipsProvider(this._actions)\n\n        this._contextMenuManager = new ContextMenuManager(this._toolTipsProvider)\n\n        this._neovimInstance = new NeovimInstance(100, 100, this._configuration)\n        this._bufferManager = new BufferManager(this._neovimInstance, this._actions, this._store)\n        this._screen = new NeovimScreen()\n\n        this._screenWithPredictions = new ScreenWithPredictions(this._screen, this._configuration)\n\n        this._hoverRenderer = new HoverRenderer(this, this._configuration, this._toolTipsProvider)\n\n        this._definition = new Definition(this, this._store)\n        this._symbols = new Symbols(\n            this,\n            this._definition,\n            this._languageManager,\n            this._menuManager,\n        )\n\n        this._diagnostics.onErrorsChanged.subscribe(() => {\n            const errors = this._diagnostics.getErrors()\n            this._actions.setErrors(errors)\n        })\n\n        this._externalMenuOverlay = this._overlayManager.createItem()\n        this._externalMenuOverlay.setContents(\n            <Provider store={this._store}>\n                <ExternalMenus>\n                    <CommandLine />\n                    <WildMenu />\n                </ExternalMenus>\n            </Provider>,\n        )\n\n        this._popupMenu = new NeovimPopupMenu(\n            this._neovimInstance.onShowPopupMenu,\n            this._neovimInstance.onHidePopupMenu,\n            this._neovimInstance.onSelectPopupMenu,\n            this.onBufferEnter,\n            this._toolTipsProvider,\n        )\n\n        const notificationManager = getNotificationsInstance()\n        this._neovimInstance.onMessage.subscribe(messageInfo => {\n            // TODO: Hook up real notifications\n            const notification = notificationManager.createItem()\n            notification.setLevel(\"error\")\n            notification.setContents(messageInfo.title, messageInfo.details)\n            notification.onClick.subscribe(() =>\n                commandManager.executeCommand(\"oni.config.openInitVim\"),\n            )\n            notification.show()\n        })\n\n        const initVimPath = this._neovimInstance.doesInitVimExist()\n        const initVimInUse = this._configuration.getValue(\"oni.loadInitVim\")\n        const hasCheckedInitVim = this._configuration.getValue(\"_internal.hasCheckedInitVim\")\n\n        if (initVimPath && !initVimInUse && !hasCheckedInitVim) {\n            const initVimNotification = notificationManager.createItem()\n            initVimNotification.setLevel(\"info\")\n            initVimNotification.setContents(\n                \"init.vim found\",\n                `We found an init.vim file would you like Oni to use it?\n                This will result in Oni being reloaded`,\n            )\n\n            initVimNotification.setButtons([\n                {\n                    title: \"Yes\",\n                    callback: () => {\n                        this._configuration.setValues(\n                            { \"_internal.hasCheckedInitVim\": true, \"oni.loadInitVim\": true },\n                            true,\n                        )\n                        commandManager.executeCommand(\"oni.debug.reload\")\n                    },\n                },\n                {\n                    title: \"No\",\n                    callback: () => {\n                        this._configuration.setValues(\n                            { \"oni.loadInitVim\": false, \"_internal.hasCheckedInitVim\": true },\n                            true,\n                        )\n                    },\n                },\n            ])\n            initVimNotification.show()\n        }\n\n        const ligaturesEnabled = this._configuration.getValue(\"editor.fontLigatures\")\n        this._renderer =\n            this._configuration.getValue(\"editor.renderer\") === \"webgl\"\n                ? new WebGLRenderer(ligaturesEnabled)\n                : new CanvasRenderer()\n\n        this._rename = new Rename(\n            this,\n            this._languageManager,\n            this._toolTipsProvider,\n            this._workspace,\n        )\n\n        // Services\n        const onColorsChanged = () => {\n            const updatedColors = this._colors.getColors()\n            this._actions.setColors(updatedColors)\n        }\n\n        this._colors.onColorsChanged.subscribe(onColorsChanged)\n        onColorsChanged()\n\n        this.trackDisposable(\n            this._tokenColors.onTokenColorsChanged.subscribe(() => {\n                if (this._neovimInstance.isInitialized) {\n                    this._syntaxHighlighter.notifyColorschemeRedraw(`${this.activeBuffer.id}`)\n                }\n            }),\n        )\n\n        // Overlays\n        // TODO: Replace `OverlayManagement` concept and associated window management code with\n        // explicit window management: #362\n        this._windowManager = new NeovimWindowManager(this._neovimInstance)\n        this.trackDisposable(\n            this._neovimInstance.onCommandLineShow.subscribe(showCommandLineInfo => {\n                this._actions.showCommandLine(\n                    showCommandLineInfo.content,\n                    showCommandLineInfo.pos,\n                    showCommandLineInfo.firstc,\n                    showCommandLineInfo.prompt,\n                    showCommandLineInfo.indent,\n                    showCommandLineInfo.level,\n                )\n                this._externalMenuOverlay.show()\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onWildMenuShow.subscribe(wildMenuInfo => {\n                this._actions.showWildMenu(wildMenuInfo)\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onWildMenuSelect.subscribe(wildMenuInfo => {\n                this._actions.wildMenuSelect(wildMenuInfo)\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onWildMenuHide.subscribe(() => {\n                this._actions.hideWildMenu()\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onCommandLineHide.subscribe(() => {\n                this._actions.hideCommandLine()\n                this._externalMenuOverlay.hide()\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onCommandLineSetCursorPosition.subscribe(commandLinePos => {\n                this._actions.setCommandLinePosition(commandLinePos)\n            }),\n        )\n\n        this.trackDisposable(\n            this._windowManager.onWindowStateChanged.subscribe(tabPageState => {\n                if (!tabPageState) {\n                    return\n                }\n                const filteredTabState = tabPageState.inactiveWindows.filter(w => !!w)\n                const inactiveIds = filteredTabState.map(w => w.windowNumber)\n\n                this._actions.setActiveVimTabPage(tabPageState.tabId, [\n                    tabPageState.activeWindow.windowNumber,\n                    ...inactiveIds,\n                ])\n\n                const { activeWindow } = tabPageState\n                if (activeWindow) {\n                    this._actions.setWindowState(\n                        activeWindow.windowNumber,\n                        activeWindow.bufferId,\n                        activeWindow.bufferFullPath,\n                        activeWindow.column,\n                        activeWindow.line,\n                        activeWindow.bottomBufferLine,\n                        activeWindow.topBufferLine,\n                        activeWindow.dimensions,\n                        activeWindow.bufferToScreen,\n                        activeWindow.visibleLines,\n                    )\n                }\n\n                filteredTabState.map(w => {\n                    this._actions.setInactiveWindowState(w.windowNumber, w.dimensions)\n                })\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onYank.subscribe(yankInfo => {\n                if (this._configuration.getValue(\"editor.clipboard.enabled\")) {\n                    const isYankAndAllowed =\n                        yankInfo.operator === \"y\" &&\n                        this._configuration.getValue(\"editor.clipboard.synchronizeYank\")\n                    const isDeleteAndAllowed =\n                        yankInfo.operator === \"d\" &&\n                        this._configuration.getValue(\"editor.clipboard.synchronizeDelete\")\n                    const isAllowed = isYankAndAllowed || isDeleteAndAllowed\n\n                    if (isAllowed) {\n                        const content = yankInfo.regcontents.join(os.EOL)\n                        const postfix = yankInfo.regtype === \"V\" ? os.EOL : \"\"\n                        clipboard.writeText(content + postfix)\n                    }\n                }\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onTitleChanged.subscribe(newTitle => {\n                const title = newTitle.replace(\" - NVIM\", \" - ONI\")\n                Shell.Actions.setWindowTitle(title)\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onLeave.subscribe(() => {\n                this._onNeovimQuit.dispatch()\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onOniCommand.subscribe(context => {\n                const commandToExecute = context.command\n                const commandArgs = context.args\n\n                commandManager.executeCommand(commandToExecute, commandArgs)\n            }),\n        )\n\n        // TODO: Refactor to event and track disposable\n        this.trackDisposable(\n            this._neovimInstance.onVimEvent.subscribe(evt => {\n                if (evt.eventName !== \"VimLeave\") {\n                    this._updateWindow(evt.eventContext)\n                    this._bufferManager.updateBufferFromEvent(evt.eventContext)\n                }\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufDelete.subscribe((evt: BufferEventContext) =>\n                this._onBufDelete(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufUnload.subscribe((evt: BufferEventContext) =>\n                this._onBufUnload(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufEnter.subscribe((evt: BufferEventContext) =>\n                this._onBufEnter(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufWinEnter.subscribe((evt: BufferEventContext) =>\n                this._onBufEnter(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onFileTypeChanged.subscribe((evt: EventContext) =>\n                this._onFileTypeChanged(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufWipeout.subscribe((evt: BufferEventContext) =>\n                this._onBufWipeout(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufWritePost.subscribe((evt: EventContext) =>\n                this._onBufWritePost(evt),\n            ),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onColorsChanged.subscribe(() => {\n                this._onColorsChanged()\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onError.subscribe(err => {\n                this._errorInitializing = true\n                this._actions.setNeovimError(true)\n            }),\n        )\n\n        // These functions are mirrors of each other if vim changes dir then oni responds\n        // and if oni initiates the dir change then we inform vim\n        // NOTE: the gates to check that the dirs being passed aren't already set prevent\n        // an infinite loop!!\n        this.trackDisposable(\n            this._neovimInstance.onDirectoryChanged.subscribe(async newDirectory => {\n                if (newDirectory !== this._workspace.activeWorkspace) {\n                    await this._workspace.changeDirectory(newDirectory)\n                }\n            }),\n        )\n\n        this.trackDisposable(\n            this._workspace.onDirectoryChanged.subscribe(async newDirectory => {\n                if (newDirectory !== this._neovimInstance.currentVimDirectory) {\n                    await this._neovimInstance.chdir(newDirectory)\n                }\n            }),\n        )\n\n        // TODO: Add first class event for this\n        this._neovimInstance.on(\"action\", (action: any) => {\n            this._renderer.onAction(action)\n            this._screen.dispatch(action)\n\n            this._scheduleRender()\n        })\n\n        this._typingPredictionManager.onPredictionsChanged.subscribe(predictions => {\n            this._screenWithPredictions.updatePredictions(predictions, this._screen.cursorRow)\n            this._renderImmediate()\n        })\n\n        this.trackDisposable(\n            this._neovimInstance.onRedrawComplete.subscribe(() => {\n                const isCursorInCommandRow = this._screen.cursorRow === this._screen.height - 1\n                const isCommandLineMode = this.mode && this.mode.indexOf(\"cmdline\") === 0\n\n                // In some cases, during redraw, Neovim will actually set the cursor position\n                // to the command line when rendering. This can happen when 'echo'ing or\n                // when a popumenu is enabled, and text is writing.\n                //\n                // We should ignore those cases, and only set the cursor in the command row\n                // when we're actually in command line mode. See #1265 for more context.\n                if (!isCursorInCommandRow || (isCursorInCommandRow && isCommandLineMode)) {\n                    this._actions.setCursorPosition(this._screen)\n                    this._typingPredictionManager.setCursorPosition(this._screen)\n                }\n            }),\n        )\n\n        // TODO: Add first class event for this\n        this._neovimInstance.on(\"tabline-update\", async (currentTabId: number, tabs: ITab[]) => {\n            const atomicCalls = tabs.map((tab: ITab) => {\n                return [\"nvim_call_function\", [\"tabpagebuflist\", [tab.id]]]\n            })\n\n            const response = await this._neovimInstance.request(\"nvim_call_atomic\", [atomicCalls])\n\n            tabs.map((tab: ITab, index: number) => {\n                tab.buffersInTab = response[0][index] instanceof Array ? response[0][index] : []\n            })\n\n            this._actions.setTabs(currentTabId, tabs)\n        })\n\n        // TODO: Does any disposal need to happen for the observables?\n        this._cursorMoved$ = asObservable(this._neovimInstance.autoCommands.onCursorMoved).map(\n            (evt): Oni.Cursor => ({\n                line: evt.line - 1,\n                column: evt.column - 1,\n            }),\n        )\n\n        this._cursorMovedI$ = asObservable(this._neovimInstance.autoCommands.onCursorMovedI).map(\n            (evt): Oni.Cursor => ({\n                line: evt.line - 1,\n                column: evt.column - 1,\n            }),\n        )\n\n        Observable.merge(this._cursorMoved$, this._cursorMovedI$).subscribe(cursorMoved => {\n            this.notifyCursorMoved(cursorMoved)\n        })\n\n        this._modeChanged$ = asObservable(this._neovimInstance.onModeChanged)\n        this._onScroll$ = asObservable(this._neovimInstance.onScroll)\n\n        this.trackDisposable(\n            this._neovimInstance.onModeChanged.subscribe(newMode => this._onModeChanged(newMode)),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onBufferUpdate.subscribe(update => {\n                const buffer = this._bufferManager.updateBufferFromEvent(update.eventContext)\n\n                const bufferUpdate = {\n                    context: update.eventContext,\n                    buffer,\n                    contentChanges: update.contentChanges,\n                }\n\n                this.notifyBufferChanged(bufferUpdate)\n                this._actions.bufferUpdate(\n                    parseInt(bufferUpdate.buffer.id, 10),\n                    bufferUpdate.buffer.modified,\n                    bufferUpdate.buffer.lineCount,\n                )\n\n                this._syntaxHighlighter.notifyBufferUpdate(bufferUpdate)\n            }),\n        )\n\n        this.trackDisposable(\n            this._neovimInstance.onScroll.subscribe((args: EventContext) => {\n                const convertedArgs: Oni.EditorBufferScrolledEventArgs = {\n                    bufferTotalLines: args.bufferTotalLines,\n                    windowTopLine: args.windowTopLine,\n                    windowBottomLine: args.windowBottomLine,\n                }\n                this.notifyBufferScrolled(convertedArgs)\n            }),\n        )\n\n        addInsertModeLanguageFunctionality(\n            this._cursorMovedI$,\n            this._modeChanged$,\n            this._onScroll$,\n            this._toolTipsProvider,\n        )\n\n        const textMateHighlightingEnabled = this._configuration.getValue(\n            \"editor.textMateHighlighting.enabled\",\n        )\n        this._syntaxHighlighter = textMateHighlightingEnabled\n            ? new SyntaxHighlighter(this, this._tokenColors)\n            : new NullSyntaxHighlighter()\n\n        this._completion = new Completion(\n            this,\n            this._configuration,\n            this._completionProviders,\n            this._languageManager,\n            this._snippetManager,\n            this._syntaxHighlighter,\n        )\n        this._completionMenu = new CompletionMenu(this._contextMenuManager.create())\n\n        this.trackDisposable(\n            this._completion.onShowCompletionItems.subscribe(completions => {\n                this._completionMenu.show(completions.filteredCompletions, completions.base)\n            }),\n        )\n\n        this.trackDisposable(\n            this._completion.onHideCompletionItems.subscribe(completions => {\n                this._completionMenu.hide()\n            }),\n        )\n\n        this.trackDisposable(\n            this._completionMenu.onItemFocused.subscribe(item => {\n                this._completion.resolveItem(item)\n            }),\n        )\n\n        this.trackDisposable(\n            this._completionMenu.onItemSelected.subscribe(item => {\n                this._completion.commitItem(item)\n            }),\n        )\n\n        this._languageIntegration = new LanguageEditorIntegration(\n            this,\n            this._configuration,\n            this._languageManager,\n        )\n\n        this.trackDisposable(\n            this._languageIntegration.onShowHover.subscribe(async hover => {\n                const { cursorPixelX, cursorPixelY } = this._store.getState()\n                await this._hoverRenderer.showQuickInfo(\n                    cursorPixelX,\n                    cursorPixelY,\n                    hover.hover,\n                    hover.errors,\n                )\n            }),\n        )\n\n        this.trackDisposable(\n            this._languageIntegration.onHideHover.subscribe(() => {\n                this._hoverRenderer.hideQuickInfo()\n            }),\n        )\n\n        this.trackDisposable(\n            this._languageIntegration.onShowDefinition.subscribe(definition => {\n                this._actions.setDefinition(definition.token, definition.location)\n            }),\n        )\n\n        this.trackDisposable(\n            this._languageIntegration.onHideDefinition.subscribe(definition => {\n                this._actions.hideDefinition()\n            }),\n        )\n\n        this._commands = new NeovimEditorCommands(\n            commandManager,\n            this._contextMenuManager,\n            this._definition,\n            this._languageIntegration,\n            this._neovimInstance,\n            this._rename,\n            this._symbols,\n        )\n\n        this._renderImmediate()\n\n        this._onConfigChanged(this._configuration.getValues())\n        this.trackDisposable(\n            this._configuration.onConfigurationChanged.subscribe(\n                (newValues: Partial<IConfigurationValues>) => this._onConfigChanged(newValues),\n            ),\n        )\n\n        // TODO: Factor these out to a place that isn't dependent on a single editor instance\n        ipcRenderer.on(\"open-files\", (_evt: any, files: string[]) => {\n            this.openFiles(files)\n        })\n\n        ipcRenderer.on(\"open-file\", (_evt: any, path: string) => {\n            this._neovimInstance.command(`:e! ${path}`)\n        })\n    }\n\n    public async blockInput(\n        inputFunction: (inputCallback: Oni.InputCallbackFunction) => Promise<void>,\n    ): Promise<void> {\n        return this._neovimInstance.blockInput(inputFunction)\n    }\n\n    public async checkMapping(\n        key: string,\n        mode: \"n\" | \"v\" | \"i\",\n    ): Promise<{ key: string; mapping: string }> {\n        return this._neovimInstance.checkUserMapping({ key, mode })\n    }\n\n    public dispose(): void {\n        super.dispose()\n\n        if (this._neovimInstance) {\n            this._neovimInstance.dispose()\n            this._neovimInstance = null\n        }\n\n        if (this._syntaxHighlighter) {\n            this._syntaxHighlighter.dispose()\n            this._syntaxHighlighter = null\n        }\n\n        if (this._languageIntegration) {\n            this._languageIntegration.dispose()\n            this._languageIntegration = null\n        }\n\n        if (this._completion) {\n            this._completion.dispose()\n            this._completion = null\n        }\n\n        if (this._externalMenuOverlay) {\n            this._externalMenuOverlay.hide()\n            this._externalMenuOverlay = null\n        }\n\n        if (this._popupMenu) {\n            this._popupMenu.dispose()\n            this._popupMenu = null\n        }\n\n        if (this._windowManager) {\n            this._windowManager.dispose()\n            this._windowManager = null\n        }\n    }\n\n    public enter(): void {\n        Log.info(\"[NeovimEditor::enter]\")\n        this._onEnterEvent.dispatch()\n        this._actions.setHasFocus(true)\n        this._commands.activate()\n\n        this._neovimInstance.autoCommands.executeAutoCommand(\"FocusGained\")\n        this.checkAutoRead()\n\n        if (this.activeBuffer) {\n            this.notifyBufferEnter(this.activeBuffer)\n        }\n    }\n\n    public checkAutoRead(): void {\n        // If the user has autoread enabled, we should run \":checktime\" on\n        // focus, as this is needed to get the file to auto-update.\n        // https://github.com/neovim/neovim/issues/1936\n        if (\n            this._neovimInstance.isInitialized &&\n            this._configuration.getValue(\"vim.setting.autoread\")\n        ) {\n            this._neovimInstance.command(\":checktime\")\n        }\n    }\n\n    public leave(): void {\n        Log.info(\"[NeovimEditor::leave]\")\n        this._actions.setHasFocus(false)\n        this._commands.deactivate()\n        this._neovimInstance.autoCommands.executeAutoCommand(\"FocusLost\")\n    }\n\n    public async createWelcomeBuffer() {\n        const buf = await this.openFile(\"WELCOME\")\n        await buf.setScratchBuffer()\n        return buf\n    }\n\n    public async clearSelection(): Promise<void> {\n        await this._neovimInstance.input(\"<esc>\")\n        await this._neovimInstance.input(\"a\")\n    }\n\n    public async setSelection(range: types.Range): Promise<void> {\n        await this._neovimInstance.input(\"<esc>\")\n\n        // Clear out any pending block selection\n        // Without this, if there was a line-wise visual selection,\n        // range selection would not work correctly.\n        const atomicCallsVisualMode = [\n            [\n                \"nvim_call_function\",\n                [\"setpos\", [\".\", [0, range.start.line + 1, range.start.character + 1]]],\n            ],\n            [\"nvim_command\", [\"normal! v\"]],\n            [\n                \"nvim_call_function\",\n                [\"setpos\", [\".\", [0, range.end.line + 1, range.end.character + 1]]],\n            ],\n        ]\n        await this._neovimInstance.request(\"nvim_call_atomic\", [atomicCallsVisualMode])\n        await this._neovimInstance.input(\"<esc>\")\n\n        // Re-select the selection and switch to 'select' mode so that typing\n        // overwrites the selection\n        const atomicCalls = [\n            [\n                \"nvim_call_function\",\n                [\"setpos\", [\"'<\", [0, range.start.line + 1, range.start.character + 1]]],\n            ],\n            [\n                \"nvim_call_function\",\n                [\"setpos\", [\"'>\", [0, range.end.line + 1, range.end.character + 1]]],\n            ],\n            // [\"nvim_command\", [\"normal! v\"]],\n            [\"nvim_command\", [\"set selectmode=cmd\"]],\n            [\"nvim_command\", [\"normal! gv\"]],\n            [\"nvim_command\", [\"set selectmode=\"]],\n        ]\n\n        await this._neovimInstance.request(\"nvim_call_atomic\", [atomicCalls])\n    }\n\n    public async setTextOptions(textOptions: Oni.EditorTextOptions): Promise<void> {\n        const { insertSpacesForTab, tabSize } = textOptions\n        if (insertSpacesForTab) {\n            await this._neovimInstance.command(\"set expandtab\")\n        } else {\n            await this._neovimInstance.command(\"set noexpandtab\")\n        }\n\n        await this._neovimInstance.command(\n            `set tabstop=${tabSize} shiftwidth=${tabSize} softtabstop=${tabSize}`,\n        )\n    }\n\n    // \"v:this_session\" |this_session-variable| - is a variable nvim sets to the path of\n    // the current session file when one is loaded we use it here to check the current session\n    // if it in oni's session dir then this is updated\n    public async getCurrentSession(): Promise<string | void> {\n        const result = await this._neovimInstance.request<string | NeovimError>(\"nvim_get_vvar\", [\n            \"this_session\",\n        ])\n\n        if (Array.isArray(result)) {\n            return this._handleNeovimError(result)\n        }\n        return result\n    }\n\n    public async persistSession(session: ISession) {\n        const result = await this._neovimInstance.command(`mksession! ${session.file}`)\n        return this._handleNeovimError(result)\n    }\n\n    public async restoreSession(session: ISession) {\n        await this._neovimInstance.closeAllBuffers()\n        const result = await this._neovimInstance.command(`source ${session.file}`)\n        return this._handleNeovimError(result)\n    }\n\n    public async openFile(\n        file: string,\n        openOptions: Oni.FileOpenOptions = Oni.DefaultFileOpenOptions,\n    ): Promise<Oni.Buffer> {\n        const tabsMode = this._configuration.getValue(\"tabs.mode\") === \"tabs\"\n        const cmd = new Proxy(\n            {\n                [Oni.FileOpenMode.NewTab]: \"tabnew!\",\n                [Oni.FileOpenMode.HorizontalSplit]: \"sp!\",\n                [Oni.FileOpenMode.VerticalSplit]: \"vsp!\",\n                [Oni.FileOpenMode.Edit]: tabsMode ? \"tab drop\" : \"e!\",\n                [Oni.FileOpenMode.ExistingTab]: \"e!\",\n            },\n            {\n                get: (target: { [cmd: string]: string }, name: string) =>\n                    name in target ? target[name] : \"e!\",\n            },\n        )\n\n        await this._neovimInstance.command(\n            `:${cmd[openOptions.openMode]} ${this._escapeSpaces(file)}`,\n        )\n        return this.activeBuffer\n    }\n\n    public openFiles = async (\n        files: string[],\n        openOptions: Oni.FileOpenOptions = Oni.DefaultFileOpenOptions,\n    ): Promise<Oni.Buffer> => {\n        if (!files) {\n            return this.activeBuffer\n        }\n\n        // Open the first file in the current buffer if there is no file there,\n        // otherwise use the passed option.\n        // Respects the users config and uses \"tab drop\" for Tab users, and \"e!\"\n        // otherwise.\n        if (this.activeBuffer.filePath === \"\") {\n            await this.openFile(files[0], { openMode: Oni.FileOpenMode.Edit })\n        } else {\n            await this.openFile(files[0], openOptions)\n        }\n\n        for (let i = 1; i < files.length; i++) {\n            await this.openFile(files[i], openOptions)\n        }\n\n        return this.activeBuffer\n    }\n\n    public async newFile(filePath: string): Promise<Oni.Buffer> {\n        await this._neovimInstance.command(\":vsp \" + filePath)\n        const context = await this._neovimInstance.getContext()\n        const buffer = this._bufferManager.updateBufferFromEvent(context)\n        return buffer\n    }\n\n    public executeCommand(command: string): void {\n        commandManager.executeCommand(command, null)\n    }\n\n    public _onFilesDropped = async (files: FileList) => {\n        if (files.length) {\n            const normalisedPaths = Array.from(files).map(f => normalizePath(f.path))\n            await this.openFiles(normalisedPaths, { openMode: Oni.FileOpenMode.Edit })\n        }\n    }\n\n    public async init(\n        filesToOpen: string[],\n        startOptions?: Partial<INeovimStartOptions>,\n    ): Promise<void> {\n        Log.info(\"[NeovimEditor::init] Called with filesToOpen: \" + filesToOpen)\n        const defaultOptions: INeovimStartOptions = {\n            runtimePaths: this._pluginManager.getAllRuntimePaths(),\n            transport: this._configuration.getValue(\"experimental.neovim.transport\"),\n            neovimPath: this._configuration.getValue(\"debug.neovimPath\"),\n            loadInitVim: this._configuration.getValue(\"oni.loadInitVim\"),\n            useDefaultConfig: this._configuration.getValue(\"oni.useDefaultConfig\"),\n        }\n\n        const combinedOptions = {\n            ...defaultOptions,\n            ...startOptions,\n        }\n\n        await this._neovimInstance.start(combinedOptions)\n\n        if (this._errorInitializing) {\n            return\n        }\n\n        VimConfigurationSynchronizer.synchronizeConfiguration(\n            this._neovimInstance,\n            this._configuration.getValues(),\n        )\n\n        this._themeManager.onThemeChanged.subscribe(() => {\n            const newTheme = this._themeManager.activeTheme\n\n            if (\n                newTheme.baseVimTheme &&\n                (newTheme.baseVimTheme !== this._currentColorScheme ||\n                    newTheme.baseVimBackground !== this._currentBackground)\n            ) {\n                this.setColorSchemeFromTheme(newTheme)\n            }\n        })\n\n        if (this._themeManager.activeTheme && this._themeManager.activeTheme.baseVimTheme) {\n            await this.setColorSchemeFromTheme(this._themeManager.activeTheme)\n        }\n\n        if (filesToOpen && filesToOpen.length > 0) {\n            await this.openFiles(filesToOpen, { openMode: Oni.FileOpenMode.Edit })\n        } else {\n            if (this._configuration.getValue(\"experimental.welcome.enabled\")) {\n                this._onShowWelcomeScreen.dispatch()\n            }\n        }\n\n        this._actions.setLoadingComplete()\n\n        this._hasLoaded = true\n        this._isFirstRender = true\n        this._scheduleRender()\n    }\n\n    public async setColorSchemeFromTheme(theme: IThemeMetadata): Promise<void> {\n        if (\n            (theme.baseVimBackground === \"dark\" || theme.baseVimBackground === \"light\") &&\n            theme.baseVimBackground !== this._currentBackground\n        ) {\n            await this._neovimInstance.command(\":set background=\" + theme.baseVimBackground)\n            this._currentBackground = theme.baseVimBackground\n        }\n\n        await this._neovimInstance.command(\":color \" + theme.baseVimTheme)\n    }\n\n    public getBuffers(): Array<Oni.Buffer | Oni.InactiveBuffer> {\n        return this._bufferManager.getBuffers()\n    }\n\n    public async bufferDelete(bufferId: string = this.activeBuffer.id): Promise<void> {\n        // FIXME: currently this command forces a bufEnter event by navigating away\n        // from the closed buffer which is currently the only means of updating Oni\n        // post a BufDelete event\n        await this._neovimInstance.command(`bd ${bufferId}`)\n        if (bufferId === \"%\" || bufferId === this.activeBuffer.id) {\n            await this._neovimInstance.command(`bnext`)\n        } else {\n            await this._neovimInstance.command(`bnext`)\n            await this._neovimInstance.command(`bprev`)\n        }\n    }\n\n    public render(): JSX.Element {\n        const onBufferClose = (bufferId: number) => {\n            this._neovimInstance.command(`bw! ${bufferId}`)\n        }\n\n        const onBufferSelect = (bufferId: number) => {\n            this._neovimInstance.command(`buf ${bufferId}`)\n        }\n\n        const onTabClose = (tabId: number) => {\n            this._neovimInstance.command(`tabclose ${tabId}`)\n        }\n\n        const onTabSelect = (tabId: number) => {\n            this._neovimInstance.command(`tabn ${tabId}`)\n        }\n\n        const onKeyDown = (key: string) => {\n            this.input(key)\n        }\n\n        return (\n            <Provider store={this._store}>\n                <NeovimSurface\n                    onFileDrop={this._onFilesDropped}\n                    renderer={this._renderer}\n                    autoFocus={this._autoFocus}\n                    typingPrediction={this._typingPredictionManager}\n                    neovimInstance={this._neovimInstance}\n                    screen={this._screen}\n                    onActivate={this._onEnterEvent}\n                    onKeyDown={onKeyDown}\n                    onBufferClose={onBufferClose}\n                    onBufferSelect={onBufferSelect}\n                    onBounceStart={() => this._onBounceStart()}\n                    onBounceEnd={() => this._onBounceEnd()}\n                    onImeStart={() => this._onImeStart()}\n                    onImeEnd={() => this._onImeEnd()}\n                    onTabClose={onTabClose}\n                    onTabSelect={onTabSelect}\n                />\n            </Provider>\n        )\n    }\n\n    public async input(key: string): Promise<void> {\n        if (this._configuration.getValue(\"debug.fakeLag.neovimInput\")) {\n            await sleep(this._configuration.getValue(\"debug.fakeLag.neovimInput\"))\n        }\n\n        // Check if any of the buffer layers can handle the input...\n        const buf = this.activeBuffer\n        const layerInputHandler = buf && buf.handleInput(key)\n\n        if (layerInputHandler) {\n            return\n        }\n\n        await this._neovimInstance.input(key)\n    }\n\n    public async quit(): Promise<void> {\n        if (this._windowManager) {\n            this._windowManager.dispose()\n            this._windowManager = null\n        }\n\n        return this._neovimInstance.quit()\n    }\n\n    private _onBounceStart(): void {\n        this._actions.setCursorScale(1.1)\n    }\n\n    private _onBounceEnd(): void {\n        this._actions.setCursorScale(1.0)\n    }\n\n    private _onModeChanged(newMode: string): void {\n        // 'Bounce' the cursor for show match\n        if (newMode === \"showmatch\") {\n            this._actions.setCursorScale(0.9)\n        }\n\n        this._typingPredictionManager.clearAllPredictions()\n\n        if (newMode === \"insert\" && this._configuration.getValue(\"editor.typingPrediction\")) {\n            this._typingPredictionManager.enable()\n        } else {\n            this._typingPredictionManager.disable()\n        }\n\n        this._actions.setMode(newMode)\n        this.setMode(newMode as Oni.Vim.Mode)\n    }\n\n    private _updateWindow(currentBuffer: EventContext) {\n        this._actions.setWindowCursor(\n            currentBuffer.windowNumber,\n            currentBuffer.line - 1,\n            currentBuffer.column - 1,\n        )\n        // Convert to 0-based positions\n        this._syntaxHighlighter.notifyViewportChanged(\n            currentBuffer.bufferNumber.toString(),\n            currentBuffer.windowTopLine - 1,\n            currentBuffer.windowBottomLine - 1,\n        )\n    }\n\n    private _onFileTypeChanged(evt: EventContext): void {\n        const buf = this._bufferManager.updateBufferFromEvent(evt)\n        this._bufferLayerManager.notifyBufferFileTypeChanged(buf)\n    }\n\n    private async _onBufEnter(evt: BufferEventContext): Promise<void> {\n        const buf = this._bufferManager.updateBufferFromEvent(evt.current)\n        this._bufferManager.populateBufferList(evt)\n        this._workspace.autoDetectWorkspace(buf.filePath)\n\n        const lastBuffer = this.activeBuffer\n        if (lastBuffer && lastBuffer.filePath !== buf.filePath) {\n            this.notifyBufferLeave({\n                filePath: lastBuffer.filePath,\n                language: lastBuffer.language,\n            })\n        }\n        this._lastBufferId = evt.current.bufferNumber.toString()\n        this.notifyBufferEnter(buf)\n        this._bufferLayerManager.notifyBufferEnter(buf)\n\n        // Existing buffers contains a duplicate current buffer object which should be filtered out\n        // and current buffer sent instead. Finally Filter out falsy viml values.\n        const existingBuffersWithoutCurrent = evt.existingBuffers.filter(\n            b => b.bufferNumber !== evt.current.bufferNumber,\n        )\n        const buffers = [evt.current, ...existingBuffersWithoutCurrent].filter(b => !!b)\n\n        this._actions.bufferEnter(buffers)\n    }\n\n    private _escapeSpaces(str: string): string {\n        return str.split(\" \").join(\"\\\\ \")\n    }\n\n    private _onImeStart(): void {\n        this._actions.setImeActive(true)\n    }\n\n    private _onImeEnd(): void {\n        this._actions.setImeActive(false)\n    }\n\n    private async _onBufWritePost(evt: EventContext): Promise<void> {\n        // After we save we aren't modified... but we can pass it in just to be safe\n        this._actions.bufferSave(evt.bufferNumber, evt.modified, evt.version)\n\n        this.notifyBufferSaved({\n            filePath: evt.bufferFullPath,\n            language: evt.filetype,\n        })\n    }\n\n    private async _onBufUnload(evt: BufferEventContext): Promise<void> {\n        this._bufferManager.populateBufferList(evt)\n        this._neovimInstance.getBufferIds().then(ids => this._actions.setCurrentBuffers(ids))\n    }\n\n    private async _onBufDelete(evt: BufferEventContext): Promise<void> {\n        this._bufferManager.populateBufferList(evt)\n        this._neovimInstance.getBufferIds().then(ids => this._actions.setCurrentBuffers(ids))\n    }\n\n    private async _onBufWipeout(evt: BufferEventContext): Promise<void> {\n        this._bufferManager.populateBufferList(evt)\n        this._neovimInstance.getBufferIds().then(ids => this._actions.setCurrentBuffers(ids))\n    }\n\n    private _onConfigChanged(newValues: Partial<IConfigurationValues>): void {\n        const fontFamily = this._configuration.getValue(\"editor.fontFamily\")\n        const fontSize = addDefaultUnitIfNeeded(this._configuration.getValue(\"editor.fontSize\"))\n        const fontWeight = this._configuration.getValue(\"editor.fontWeight\")\n        const linePadding = this._configuration.getValue(\"editor.linePadding\")\n\n        this._actions.setFont(fontFamily, fontSize, fontWeight)\n        this._neovimInstance.setFont(fontFamily, fontSize, fontWeight, linePadding)\n\n        Object.keys(newValues).forEach(key => {\n            const value = newValues[key]\n            this._actions.setConfigValue(key, value)\n        })\n\n        if (this._hasLoaded) {\n            VimConfigurationSynchronizer.synchronizeConfiguration(this._neovimInstance, newValues)\n        }\n\n        this._isFirstRender = true\n\n        this._scheduleRender()\n    }\n\n    private async _onColorsChanged(): Promise<void> {\n        const newColorScheme = await this._neovimInstance.eval<string>(\"g:colors_name\")\n        const { bufferNumber } = await this._neovimInstance.getContext()\n        this._syntaxHighlighter.notifyColorschemeRedraw(`${bufferNumber}`)\n\n        // In error cases, the neovim API layer returns an array\n        if (typeof newColorScheme !== \"string\") {\n            return\n        }\n\n        this._currentColorScheme = newColorScheme\n        const backgroundColor = this._screen.backgroundColor\n        const foregroundColor = this._screen.foregroundColor\n\n        Log.info(\n            `[NeovimEditor] Colors changed: ${newColorScheme} - background: ${backgroundColor} foreground: ${foregroundColor}`,\n        )\n\n        this._themeManager.notifyVimThemeChanged(newColorScheme, backgroundColor, foregroundColor)\n\n        const tokenColors = await this._neovimInstance.getTokenColors()\n        this._tokenColors.setDefaultTokenColors(tokenColors)\n\n        // Flip first render to force a full redraw\n        this._isFirstRender = true\n        this._scheduleRender()\n    }\n\n    private _scheduleRender(): void {\n        if (this._pendingAnimationFrame) {\n            return\n        }\n\n        this._pendingAnimationFrame = true\n        window.requestAnimationFrame(() => this._renderImmediate())\n    }\n\n    private _renderImmediate(): void {\n        this._pendingAnimationFrame = false\n\n        if (this._hasLoaded) {\n            if (this._isFirstRender) {\n                this._isFirstRender = false\n                this._renderer.redrawAll(this._screenWithPredictions as any)\n            } else {\n                this._renderer.draw(this._screenWithPredictions as any)\n            }\n        }\n    }\n\n    private _handleNeovimError(result: NeovimError | void): void {\n        if (!result) {\n            return null\n        }\n        // the first value of the error response is a 0\n        if (Array.isArray(result) && !result[0]) {\n            const [, error] = result\n            Log.warn(error)\n            throw new Error(error)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditorActions.ts",
    "content": "/**\n * ActionCreators.ts\n *\n * Action Creators are relatively simple - they are just a function that returns an `Action`\n *\n * For information on Action Creators, check out this link:\n * http://redux.js.org/docs/basics/Actions.html\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as State from \"./NeovimEditorStore\"\n\nimport { EventContext, InactiveBufferContext, IScreen } from \"./../../neovim\"\nimport { normalizePath } from \"./../../Utility\"\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\nimport { Errors } from \"./../../Services/Diagnostics\"\nimport { IThemeColors } from \"./../../Services/Themes\"\n\nimport { IBufferLayer } from \"./../NeovimEditor/BufferLayerManager\"\n\nexport type DispatchFunction = (action: any) => void\nexport type GetStateFunction = () => State.IState\n\nexport interface ISetHasFocusAction {\n    type: \"SET_HAS_FOCUS\"\n    payload: {\n        hasFocus: boolean\n    }\n}\n\nexport interface ISetLoadingCompleteAction {\n    type: \"SET_LOADING_COMPLETE\"\n}\n\nexport interface ISetColorsAction {\n    type: \"SET_COLORS\"\n    payload: {\n        colors: IThemeColors\n    }\n}\n\nexport interface IAddBufferLayerAction {\n    type: \"ADD_BUFFER_LAYER\"\n    payload: {\n        bufferId: number\n        layer: IBufferLayer\n    }\n}\n\nexport interface IRemoveBufferLayerAction {\n    type: \"REMOVE_BUFFER_LAYER\"\n    payload: {\n        bufferId: number\n        layer: IBufferLayer\n    }\n}\n\nexport interface ISetViewportAction {\n    type: \"SET_VIEWPORT\"\n    payload: {\n        width: number\n        height: number\n    }\n}\n\nexport interface ISetCommandLinePosition {\n    type: \"SET_COMMAND_LINE_POSITION\"\n    payload: {\n        position: number\n        level: number\n    }\n}\n\nexport interface IHideCommandLineAction {\n    type: \"HIDE_COMMAND_LINE\"\n}\n\nexport interface IShowCommandLineAction {\n    type: \"SHOW_COMMAND_LINE\"\n    payload: {\n        content: Array<[any, string]>\n        position: number\n        firstchar: string\n        prompt: string\n        indent: number\n        level: number\n    }\n}\n\nexport interface IWildMenuSelectedAction {\n    type: \"WILDMENU_SELECTED\"\n    payload: {\n        selected: number\n    }\n}\n\nexport interface IShowWildMenuAction {\n    type: \"SHOW_WILDMENU\"\n    payload: {\n        options: string[]\n    }\n}\n\nexport interface IHideWildMenuAction {\n    type: \"HIDE_WILDMENU\"\n}\n\nexport interface ISetNeovimErrorAction {\n    type: \"SET_NEOVIM_ERROR\"\n    payload: {\n        neovimError: boolean\n    }\n}\n\nexport interface ISetCursorScaleAction {\n    type: \"SET_CURSOR_SCALE\"\n    payload: {\n        cursorScale: number\n    }\n}\n\nexport interface ISetCurrentBuffersAction {\n    type: \"SET_CURRENT_BUFFERS\"\n    payload: {\n        bufferIds: number[]\n    }\n}\n\nexport interface ISetImeActive {\n    type: \"SET_IME_ACTIVE\"\n    payload: {\n        imeActive: boolean\n    }\n}\n\nexport interface ISetFont {\n    type: \"SET_FONT\"\n    payload: {\n        fontFamily: string\n        fontSize: string\n        fontWeight: string\n    }\n}\n\nexport interface IBufferEnterAction {\n    type: \"BUFFER_ENTER\"\n    payload: {\n        buffers: State.IBuffer[]\n    }\n}\n\nexport interface IShowToolTipAction {\n    type: \"SHOW_TOOL_TIP\"\n    payload: {\n        id: string\n        element: JSX.Element\n        options?: Oni.ToolTip.ToolTipOptions\n    }\n}\n\nexport interface IHideToolTipAction {\n    type: \"HIDE_TOOL_TIP\"\n    payload: {\n        id: string\n    }\n}\n\nexport interface IBufferUpdateAction {\n    type: \"BUFFER_UPDATE\"\n    payload: {\n        id: number\n        modified: boolean\n        version: number\n        totalLines: number\n    }\n}\n\nexport interface IBufferSaveAction {\n    type: \"BUFFER_SAVE\"\n    payload: {\n        id: number\n        modified: boolean\n        version: number\n    }\n}\n\nexport interface ISetTabs {\n    type: \"SET_TABS\"\n    payload: {\n        selectedTabId: number\n        tabs: State.ITab[]\n    }\n}\n\nexport interface ISetActiveVimTabPage {\n    type: \"SET_ACTIVE_VIM_TAB_PAGE\"\n    payload: {\n        id: number\n        windowIds: number[]\n    }\n}\n\nexport interface ISetWindowCursor {\n    type: \"SET_WINDOW_CURSOR\"\n    payload: {\n        windowId: number\n        line: number\n        column: number\n    }\n}\n\nexport interface ISetWindowState {\n    type: \"SET_WINDOW_STATE\"\n    payload: {\n        windowId: number\n        bufferId: number\n        file: string\n        column: number\n        line: number\n\n        dimensions: Oni.Shapes.Rectangle\n\n        bufferToScreen: Oni.Coordinates.BufferToScreen\n        screenToPixel: Oni.Coordinates.ScreenToPixel\n        bufferToPixel: Oni.Coordinates.BufferToPixel\n\n        topBufferLine: number\n        bottomBufferLine: number\n        visibleLines: string[]\n    }\n}\n\nexport interface ISetInactiveWindowState {\n    type: \"SET_INACTIVE_WINDOW_STATE\"\n    payload: {\n        windowId: number\n        dimensions: Oni.Shapes.Rectangle\n    }\n}\n\nexport interface ISetErrorsAction {\n    type: \"SET_ERRORS\"\n    payload: {\n        errors: Errors\n    }\n}\n\nexport interface ISetCursorPositionAction {\n    type: \"SET_CURSOR_POSITION\"\n    payload: {\n        pixelX: number\n        pixelY: number\n        fontPixelWidth: number\n        fontPixelHeight: number\n        cursorCharacter: string\n        cursorPixelWidth: number\n    }\n}\n\nexport interface ISetModeAction {\n    type: \"SET_MODE\"\n    payload: {\n        mode: string\n    }\n}\n\nexport interface IShowDefinitionAction {\n    type: \"SHOW_DEFINITION\"\n    payload: {\n        token: Oni.IToken\n        definitionLocation: types.Location\n    }\n}\n\nexport interface IHideDefinitionAction {\n    type: \"HIDE_DEFINITION\"\n}\n\nexport interface ISetConfigurationValue<K extends keyof IConfigurationValues> {\n    type: \"SET_CONFIGURATION_VALUE\"\n    payload: {\n        key: K\n        value: IConfigurationValues[K]\n    }\n}\n\nexport type Action<K extends keyof IConfigurationValues> = SimpleAction | ActionWithGeneric<K>\n\nexport type SimpleAction =\n    | IAddBufferLayerAction\n    | IRemoveBufferLayerAction\n    | IBufferEnterAction\n    | IBufferSaveAction\n    | IBufferUpdateAction\n    | ISetColorsAction\n    | ISetCursorPositionAction\n    | ISetImeActive\n    | ISetFont\n    | IHideToolTipAction\n    | IShowToolTipAction\n    | IHideDefinitionAction\n    | IShowDefinitionAction\n    | ISetModeAction\n    | ISetCursorScaleAction\n    | ISetErrorsAction\n    | ISetCurrentBuffersAction\n    | ISetHasFocusAction\n    | ISetNeovimErrorAction\n    | ISetTabs\n    | ISetActiveVimTabPage\n    | ISetLoadingCompleteAction\n    | ISetViewportAction\n    | ISetWindowCursor\n    | ISetWindowState\n    | ISetInactiveWindowState\n    | IShowCommandLineAction\n    | IHideCommandLineAction\n    | ISetCommandLinePosition\n    | IHideWildMenuAction\n    | IShowWildMenuAction\n    | IWildMenuSelectedAction\n\nexport type ActionWithGeneric<K extends keyof IConfigurationValues> = ISetConfigurationValue<K>\n\nexport const setHasFocus = (hasFocus: boolean) => {\n    return {\n        type: \"SET_HAS_FOCUS\",\n        payload: {\n            hasFocus,\n        },\n    }\n}\n\nexport const setLoadingComplete = () => {\n    return {\n        type: \"SET_LOADING_COMPLETE\",\n    }\n}\n\nexport const setColors = (colors: IThemeColors) => ({\n    type: \"SET_COLORS\",\n    payload: {\n        colors,\n    },\n})\n\nexport const setCommandLinePosition = ({\n    pos: position,\n    level,\n}: {\n    pos: number\n    level: number\n}) => ({\n    type: \"SET_COMMAND_LINE_POSITION\",\n    payload: {\n        position,\n        level,\n    },\n})\n\nexport const hideCommandLine = () => ({\n    type: \"HIDE_COMMAND_LINE\",\n})\n\nexport const showCommandLine = (\n    content: Array<[any, string]>,\n    pos: number,\n    firstchar: string,\n    prompt: string,\n    indent: number,\n    level: number,\n) => ({\n    type: \"SHOW_COMMAND_LINE\",\n    payload: {\n        content,\n        position: pos,\n        firstchar,\n        prompt,\n        indent,\n        level,\n    },\n})\n\nexport const showWildMenu = (payload: { options: string[] }) => ({\n    type: \"SHOW_WILDMENU\",\n    payload,\n})\n\nexport const wildMenuSelect = (payload: { selected: number }) => ({\n    type: \"WILDMENU_SELECTED\",\n    payload,\n})\n\nexport const hideWildMenu = () => ({\n    type: \"HIDE_WILDMENU\",\n})\n\nexport const setNeovimError = (neovimError: boolean) => ({\n    type: \"SET_NEOVIM_ERROR\",\n    payload: {\n        neovimError,\n    },\n})\n\nexport const setViewport = (width: number, height: number) => ({\n    type: \"SET_VIEWPORT\",\n    payload: {\n        width,\n        height,\n    },\n})\n\nexport const setCursorScale = (cursorScale: number) => ({\n    type: \"SET_CURSOR_SCALE\",\n    payload: {\n        cursorScale,\n    },\n})\n\nconst formatBuffers = (buffer: InactiveBufferContext & EventContext) => {\n    return {\n        id: buffer.bufferNumber,\n        file: buffer.bufferFullPath ? normalizePath(buffer.bufferFullPath) : \"\",\n        totalLines: buffer.bufferTotalLines ? buffer.bufferTotalLines : null,\n        language: buffer.filetype,\n        hidden: buffer.hidden,\n        listed: buffer.listed,\n        modified: buffer.modified,\n    }\n}\n\nexport const addBufferLayer = (\n    bufferId: number,\n    layer: Oni.BufferLayer,\n): IAddBufferLayerAction => ({\n    type: \"ADD_BUFFER_LAYER\",\n    payload: {\n        bufferId,\n        layer,\n    },\n})\n\nexport const removeBufferLayer = (\n    bufferId: number,\n    layer: Oni.BufferLayer,\n): IRemoveBufferLayerAction => ({\n    type: \"REMOVE_BUFFER_LAYER\",\n    payload: {\n        bufferId,\n        layer,\n    },\n})\n\nexport const bufferEnter = (buffers: Array<InactiveBufferContext | EventContext>) => ({\n    type: \"BUFFER_ENTER\",\n    payload: {\n        buffers: buffers.map(formatBuffers),\n    },\n})\n\nexport const bufferUpdate = (id: number, modified: boolean, totalLines: number) => ({\n    type: \"BUFFER_UPDATE\",\n    payload: {\n        id,\n        modified,\n        totalLines,\n    },\n})\n\nexport const bufferSave = (id: number, modified: boolean, version: number) => ({\n    type: \"BUFFER_SAVE\",\n    payload: {\n        id,\n        modified,\n        version,\n    },\n})\n\nexport const setCurrentBuffers = (bufferIds: number[]) => ({\n    type: \"SET_CURRENT_BUFFERS\",\n    payload: {\n        bufferIds,\n    },\n})\n\nexport const setImeActive = (imeActive: boolean) => ({\n    type: \"SET_IME_ACTIVE\",\n    payload: {\n        imeActive,\n    },\n})\n\nexport const setFont = (fontFamily: string, fontSize: string, fontWeight: string) => ({\n    type: \"SET_FONT\",\n    payload: {\n        fontFamily,\n        fontSize,\n        fontWeight,\n    },\n})\n\nexport const setTabs = (selectedTabId: number, tabs: State.ITab[]): ISetTabs => ({\n    type: \"SET_TABS\",\n    payload: {\n        selectedTabId,\n        tabs,\n    },\n})\n\nexport const setWindowCursor = (windowId: number, line: number, column: number) => ({\n    type: \"SET_WINDOW_CURSOR\",\n    payload: {\n        windowId,\n        line,\n        column,\n    },\n})\n\nexport const setWindowState = (\n    windowId: number,\n    bufferId: number,\n    file: string,\n    column: number,\n    line: number,\n    bottomBufferLine: number,\n    topBufferLine: number,\n    dimensions: Oni.Shapes.Rectangle,\n    bufferToScreen: Oni.Coordinates.BufferToScreen,\n    visibleLines: string[],\n) => (dispatch: DispatchFunction, getState: GetStateFunction) => {\n    const { fontPixelWidth, fontPixelHeight } = getState()\n\n    const screenToPixel = (screenSpace: Oni.Coordinates.ScreenSpacePoint) => {\n        if (\n            !screenSpace ||\n            typeof screenSpace.screenX !== \"number\" ||\n            typeof screenSpace.screenY !== \"number\"\n        ) {\n            return {\n                pixelX: NaN,\n                pixelY: NaN,\n            }\n        }\n\n        return {\n            pixelX: screenSpace.screenX * fontPixelWidth,\n            pixelY: screenSpace.screenY * fontPixelHeight,\n        }\n    }\n\n    const bufferToPixel = (position: types.Position): Oni.Coordinates.PixelSpacePoint => {\n        const screenPosition = bufferToScreen(position)\n\n        if (!screenPosition) {\n            return null\n        }\n\n        return screenToPixel(screenPosition)\n    }\n\n    dispatch({\n        type: \"SET_WINDOW_STATE\",\n        payload: {\n            windowId,\n            bufferId,\n            file: normalizePath(file),\n            column,\n            dimensions,\n            line,\n            bufferToScreen,\n            screenToPixel,\n            bufferToPixel,\n            bottomBufferLine,\n            topBufferLine,\n            visibleLines,\n        },\n    })\n}\n\nexport const setInactiveWindowState = (\n    windowId: number,\n    dimensions: Oni.Shapes.Rectangle,\n): ISetInactiveWindowState => ({\n    type: \"SET_INACTIVE_WINDOW_STATE\",\n    payload: {\n        windowId,\n        dimensions,\n    },\n})\n\nexport const showToolTip = (\n    id: string,\n    element: JSX.Element,\n    options?: Oni.ToolTip.ToolTipOptions,\n) => ({\n    type: \"SHOW_TOOL_TIP\",\n    payload: {\n        id,\n        element,\n        options,\n    },\n})\n\nexport const hideToolTip = (id: string) => ({\n    type: \"HIDE_TOOL_TIP\",\n    payload: {\n        id,\n    },\n})\n\nexport const setErrors = (errors: Errors) => ({\n    type: \"SET_ERRORS\",\n    payload: {\n        errors,\n    },\n})\n\nexport const setCursorPosition = (screen: IScreen) => (dispatch: DispatchFunction) => {\n    const cell = screen.getCell(screen.cursorColumn, screen.cursorRow)\n\n    dispatch(\n        _setCursorPosition(\n            screen.cursorColumn * screen.fontWidthInPixels,\n            screen.cursorRow * screen.fontHeightInPixels,\n            screen.fontWidthInPixels,\n            screen.fontHeightInPixels,\n            cell.character,\n            cell.characterWidth * screen.fontWidthInPixels,\n        ),\n    )\n}\n\nexport const setMode = (mode: string) => ({\n    type: \"SET_MODE\",\n    payload: { mode },\n})\n\nexport const setDefinition = (\n    token: Oni.IToken,\n    definitionLocation: types.Location,\n): IShowDefinitionAction => ({\n    type: \"SHOW_DEFINITION\",\n    payload: {\n        token,\n        definitionLocation,\n    },\n})\n\nexport const hideDefinition = () => ({\n    type: \"HIDE_DEFINITION\",\n})\n\nexport const setCursorLineOpacity = (opacity: number) => ({\n    type: \"SET_CURSOR_LINE_OPACITY\",\n    payload: {\n        opacity,\n    },\n})\n\nexport const setCursorColumnOpacity = (opacity: number) => ({\n    type: \"SET_CURSOR_COLUMN_OPACITY\",\n    payload: {\n        opacity,\n    },\n})\n\nexport const setActiveVimTabPage = (tabId: number, windowIds: number[]): ISetActiveVimTabPage => ({\n    type: \"SET_ACTIVE_VIM_TAB_PAGE\",\n    payload: {\n        id: tabId,\n        windowIds,\n    },\n})\n\nexport function setConfigValue<K extends keyof IConfigurationValues>(\n    k: K,\n    v: IConfigurationValues[K],\n): ISetConfigurationValue<K> {\n    return {\n        type: \"SET_CONFIGURATION_VALUE\",\n        payload: {\n            key: k,\n            value: v,\n        },\n    }\n}\n\nconst _setCursorPosition = (\n    cursorPixelX: any,\n    cursorPixelY: any,\n    fontPixelWidth: any,\n    fontPixelHeight: any,\n    cursorCharacter: string,\n    cursorPixelWidth: number,\n) => ({\n    type: \"SET_CURSOR_POSITION\",\n    payload: {\n        pixelX: cursorPixelX,\n        pixelY: cursorPixelY,\n        fontPixelWidth,\n        fontPixelHeight,\n        cursorCharacter,\n        cursorPixelWidth,\n    },\n})\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditorCommands.ts",
    "content": "/**\n * NeovimEditorCommands\n *\n * Contextual commands for NeovimEditor\n *\n */\nimport * as os from \"os\"\n\nimport { clipboard } from \"electron\"\nimport * as Oni from \"oni-api\"\n\nimport { NeovimInstance } from \"./../../neovim\"\nimport { CallbackCommand, CommandManager } from \"./../../Services/CommandManager\"\nimport { ContextMenuManager } from \"./../../Services/ContextMenu\"\nimport { editorManager } from \"./../../Services/EditorManager\"\nimport { findAllReferences, format, LanguageEditorIntegration } from \"./../../Services/Language\"\nimport { replaceAll } from \"./../../Utility\"\n\nimport { Definition } from \"./Definition\"\nimport { Rename } from \"./Rename\"\nimport { Symbols } from \"./Symbols\"\n\nexport class NeovimEditorCommands {\n    private _lastCommands: CallbackCommand[] = []\n\n    constructor(\n        private _commandManager: CommandManager,\n        private _contextMenuManager: ContextMenuManager,\n        private _definition: Definition,\n        private _languageEditorIntegration: LanguageEditorIntegration,\n        private _neovimInstance: NeovimInstance,\n        private _rename: Rename,\n        private _symbols: Symbols,\n    ) {}\n\n    public activate(): void {\n        const isContextMenuOpen = () => this._contextMenuManager.isMenuOpen()\n\n        /**\n         * Higher-order function for commands dealing with completion\n         * - checks that the completion menu is open\n         */\n        const contextMenuCommand = (innerCommand: Oni.Commands.CommandCallback) => {\n            return () => {\n                if (this._contextMenuManager.isMenuOpen()) {\n                    return innerCommand()\n                }\n\n                return false\n            }\n        }\n\n        const selectContextMenuItem = contextMenuCommand(() => {\n            this._contextMenuManager.selectMenuItem()\n        })\n\n        const nextContextMenuItem = contextMenuCommand(() => {\n            this._contextMenuManager.nextMenuItem()\n        })\n\n        const closeContextMenu = contextMenuCommand(() => {\n            this._contextMenuManager.closeActiveMenu()\n        })\n\n        const previousContextMenuItem = contextMenuCommand(() => {\n            this._contextMenuManager.previousMenuItem()\n        })\n\n        const pasteContents = async (neovimInstance: NeovimInstance) => {\n            const textToPaste = clipboard.readText()\n            const replacements = { \"'\": \"''\" }\n            replacements[os.EOL] = \"\\n\"\n            const sanitizedTextLines = replaceAll(textToPaste, replacements)\n            await neovimInstance.command('let b:oniclipboard=@\"')\n            await neovimInstance.command(`let @\"='${sanitizedTextLines}'`)\n\n            if (\n                editorManager.activeEditor.mode === \"insert\" ||\n                editorManager.activeEditor.mode === \"cmdline_normal\"\n            ) {\n                await neovimInstance.command(\"set paste\")\n                await neovimInstance.input('<c-r>\"')\n                await neovimInstance.command(\"set nopaste\")\n            } else {\n                await neovimInstance.command(\"normal! p\")\n            }\n\n            await neovimInstance.command('let @\"=b:oniclipboard')\n            await neovimInstance.command(\"unlet b:oniclipboard\")\n        }\n\n        const commands = [\n            new CallbackCommand(\n                \"contextMenu.select\",\n                null,\n                null,\n                selectContextMenuItem,\n                isContextMenuOpen,\n            ),\n            new CallbackCommand(\n                \"contextMenu.next\",\n                null,\n                null,\n                nextContextMenuItem,\n                isContextMenuOpen,\n            ),\n            new CallbackCommand(\n                \"contextMenu.previous\",\n                null,\n                null,\n                previousContextMenuItem,\n                isContextMenuOpen,\n            ),\n            new CallbackCommand(\n                \"contextMenu.close\",\n                null,\n                null,\n                closeContextMenu,\n                isContextMenuOpen,\n            ),\n\n            new CallbackCommand(\n                \"editor.clipboard.paste\",\n                \"Clipboard: Paste\",\n                \"Paste clipboard contents into active text\",\n                () => pasteContents(this._neovimInstance),\n            ),\n            new CallbackCommand(\n                \"editor.clipboard.yank\",\n                \"Clipboard: Yank\",\n                \"Yank contents to clipboard\",\n                () => this._neovimInstance.command('normal! \"+y'),\n            ),\n            new CallbackCommand(\n                \"editor.clipboard.cut\",\n                \"Clipboard: Cut\",\n                \"Cut contents to clipboard\",\n                () => this._neovimInstance.command('normal! \"+x'),\n            ),\n            new CallbackCommand(\"oni.editor.findAllReferences\", null, null, () =>\n                findAllReferences(),\n            ),\n            new CallbackCommand(\n                \"language.findAllReferences\",\n                \"Find All References\",\n                \"Find all references using a language service\",\n                () => findAllReferences(),\n            ),\n\n            new CallbackCommand(\"language.format\", null, null, () => format()),\n\n            // TODO: Deprecate\n            new CallbackCommand(\"oni.editor.gotoDefinition\", null, null, () =>\n                this._definition.gotoDefinitionUnderCursor(),\n            ),\n            new CallbackCommand(\n                \"language.gotoDefinition\",\n                \"Goto Definition\",\n                \"Goto definition using a language service\",\n                () => this._definition.gotoDefinitionUnderCursor(),\n            ),\n            new CallbackCommand(\"language.gotoDefinition.openVertical\", null, null, () =>\n                this._definition.gotoDefinitionUnderCursor({\n                    openMode: Oni.FileOpenMode.VerticalSplit,\n                }),\n            ),\n            new CallbackCommand(\"language.gotoDefinition.openHorizontal\", null, null, () =>\n                this._definition.gotoDefinitionUnderCursor({\n                    openMode: Oni.FileOpenMode.HorizontalSplit,\n                }),\n            ),\n            new CallbackCommand(\"language.gotoDefinition.openNewTab\", null, null, () =>\n                this._definition.gotoDefinitionUnderCursor({ openMode: Oni.FileOpenMode.NewTab }),\n            ),\n            new CallbackCommand(\"language.gotoDefinition.openEdit\", null, null, () =>\n                this._definition.gotoDefinitionUnderCursor({ openMode: Oni.FileOpenMode.Edit }),\n            ),\n            new CallbackCommand(\"language.gotoDefinition.openExistingTab\", null, null, () =>\n                this._definition.gotoDefinitionUnderCursor({\n                    openMode: Oni.FileOpenMode.ExistingTab,\n                }),\n            ),\n\n            new CallbackCommand(\"editor.rename\", \"Rename\", \"Rename an item\", () =>\n                this._rename.startRename(),\n            ),\n\n            new CallbackCommand(\"editor.quickInfo.show\", null, null, () =>\n                this._languageEditorIntegration.showHover(),\n            ),\n\n            new CallbackCommand(\"language.symbols.document\", null, null, () =>\n                this._symbols.openDocumentSymbolsMenu(),\n            ),\n            new CallbackCommand(\"language.symbols.workspace\", null, null, () =>\n                this._symbols.openWorkspaceSymbolsMenu(),\n            ),\n            new CallbackCommand(\n                \"oni.config.openInitVim\",\n                \"Configuration: Edit Neovim Config\",\n                \"Edit configuration file ('init.vim') for Neovim\",\n                () => this._neovimInstance.openInitVim(),\n            ),\n        ]\n\n        this._lastCommands = commands\n        commands.forEach(c => this._commandManager.registerCommand(c))\n    }\n\n    public deactivate(): void {\n        this._lastCommands.forEach(c => this._commandManager.unregisterCommand(c.command))\n        this._lastCommands = []\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditorLoadingOverlay.tsx",
    "content": "/**\n * NeovimEditorLoadingOverlay\n *\n * Overlay shown over the editor window while initializing (loading Neovim)\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport * as State from \"./NeovimEditorStore\"\n\nimport styled from \"styled-components\"\nimport { withProps } from \"./../../UI/components/common\"\n\nconst LoadingSpinnerWrapper = withProps<{}>(styled.div)`\n    background-color: ${props => props.theme[\"editor.background\"]};\n    color: ${props => props.theme[\"editor.foreground\"]};\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    opacity: 1;\n    transition: opacity 0.15s ease-in;\n\n    &.loaded {\n        opacity: 0;\n        pointer-events: none;\n    }\n`\n\nexport const NeovimEditorLoadingOverlayView = (props: { visible: boolean }): JSX.Element => {\n    const className = props.visible ? \"stack layer\" : \" stack layer loaded\"\n\n    return <LoadingSpinnerWrapper className={className} />\n}\n\nexport const mapStateToProps = (state: State.IState): { visible: boolean } => {\n    return { visible: !state.isLoaded }\n}\n\nexport const NeovimEditorLoadingOverlay = connect(mapStateToProps)(NeovimEditorLoadingOverlayView)\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditorReducer.ts",
    "content": "/**\n * Reducer.ts\n *\n * Top-level reducer for UI state transforms\n */\n\nimport * as State from \"./NeovimEditorStore\"\n\nimport * as Actions from \"./NeovimEditorActions\"\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\nimport { Errors } from \"./../../Services/Diagnostics\"\n\nimport * as pick from \"lodash/pick\"\n\nexport function reducer<K extends keyof IConfigurationValues>(\n    s: State.IState,\n    a: Actions.Action<K>,\n): State.IState {\n    if (!s) {\n        return s\n    }\n\n    switch (a.type) {\n        case \"SET_HAS_FOCUS\":\n            return {\n                ...s,\n                hasFocus: a.payload.hasFocus,\n            }\n        case \"SET_COLORS\":\n            return {\n                ...s,\n                colors: a.payload.colors,\n            }\n        case \"SET_LOADING_COMPLETE\":\n            return {\n                ...s,\n                isLoaded: true,\n            }\n        case \"SET_NEOVIM_ERROR\":\n            return {\n                ...s,\n                neovimError: a.payload.neovimError,\n            }\n        case \"SET_VIEWPORT\":\n            return {\n                ...s,\n                viewport: viewportReducer(s.viewport, a),\n            }\n        case \"SET_CURSOR_SCALE\":\n            return {\n                ...s,\n                cursorScale: a.payload.cursorScale,\n            }\n        case \"SET_ACTIVE_VIM_TAB_PAGE\":\n            return {\n                ...s,\n                activeVimTabPage: a.payload,\n            }\n        case \"SET_CURSOR_POSITION\":\n            return {\n                ...s,\n                cursorPixelX: a.payload.pixelX,\n                cursorPixelY: a.payload.pixelY,\n                fontPixelWidth: a.payload.fontPixelWidth,\n                fontPixelHeight: a.payload.fontPixelHeight,\n                cursorCharacter: a.payload.cursorCharacter,\n                cursorPixelWidth: a.payload.cursorPixelWidth,\n            }\n        case \"SET_IME_ACTIVE\":\n            return {\n                ...s,\n                imeActive: a.payload.imeActive,\n            }\n        case \"SET_FONT\":\n            return {\n                ...s,\n                fontFamily: a.payload.fontFamily,\n                fontSize: a.payload.fontSize,\n                fontWeight: a.payload.fontWeight,\n            }\n        case \"SET_MODE\":\n            return { ...s, ...{ mode: a.payload.mode } }\n        case \"SET_CONFIGURATION_VALUE\":\n            const obj: Partial<IConfigurationValues> = {}\n            obj[a.payload.key] = a.payload.value\n            const newConfig = { ...s.configuration, ...obj }\n            return {\n                ...s,\n                configuration: newConfig,\n            }\n        case \"SHOW_WILDMENU\":\n            return {\n                ...s,\n                wildmenu: {\n                    ...s.wildmenu,\n                    visible: true,\n                    options: a.payload.options,\n                },\n            }\n        case \"WILDMENU_SELECTED\":\n            return {\n                ...s,\n                wildmenu: {\n                    ...s.wildmenu,\n                    selected: a.payload.selected,\n                },\n            }\n        case \"HIDE_WILDMENU\":\n            return {\n                ...s,\n                wildmenu: {\n                    ...s.wildmenu,\n                    visible: false,\n                },\n            }\n        case \"SHOW_COMMAND_LINE\":\n            // Array<[any, string]>\n            const [[, content]] = a.payload.content\n            return {\n                ...s,\n                commandLine: {\n                    content,\n                    visible: true,\n                    position: a.payload.position,\n                    firstchar: a.payload.firstchar,\n                    prompt: a.payload.prompt,\n                    indent: a.payload.indent,\n                    level: a.payload.level,\n                },\n            }\n        case \"HIDE_COMMAND_LINE\":\n            return {\n                ...s,\n                commandLine: {\n                    visible: false,\n                    content: null,\n                    firstchar: \"\",\n                    position: null,\n                    prompt: \"\",\n                    indent: null,\n                    level: null,\n                },\n            }\n        case \"SET_COMMAND_LINE_POSITION\":\n            return {\n                ...s,\n                commandLine: {\n                    ...s.commandLine,\n                    position: a.payload.position,\n                    level: a.payload.level,\n                },\n            }\n        default:\n            return {\n                ...s,\n                buffers: buffersReducer(s.buffers, a),\n                definition: definitionReducer(s.definition, a),\n                layers: layersReducer(s.layers, a),\n                tabState: tabStateReducer(s.tabState, a),\n                errors: errorsReducer(s.errors, a),\n                toolTips: toolTipsReducer(s.toolTips, a),\n                windowState: windowStateReducer(s.windowState, a),\n            }\n    }\n}\n\nexport const layersReducer = (s: State.Layers, a: Actions.SimpleAction) => {\n    switch (a.type) {\n        case \"ADD_BUFFER_LAYER\": {\n            const currentLayers = s[a.payload.bufferId] || []\n\n            if (currentLayers.find(layer => layer.id === a.payload.layer.id)) {\n                return s\n            }\n\n            return {\n                ...s,\n                [a.payload.bufferId]: [...currentLayers, a.payload.layer],\n            }\n        }\n        case \"REMOVE_BUFFER_LAYER\": {\n            const currentLayers = s[a.payload.bufferId] || []\n            return {\n                ...s,\n                [a.payload.bufferId]: currentLayers.filter(l => l !== a.payload.layer),\n            }\n        }\n        default:\n            return s\n    }\n}\n\nexport const definitionReducer = (s: State.IDefinition, a: Actions.SimpleAction) => {\n    switch (a.type) {\n        case \"SHOW_DEFINITION\":\n            const { definitionLocation, token } = a.payload\n            return {\n                definitionLocation,\n                token,\n            }\n        case \"HIDE_DEFINITION\":\n            return null\n        default:\n            return s\n    }\n}\n\nexport const viewportReducer = (s: State.IViewport, a: Actions.ISetViewportAction) => {\n    const { width, height } = a.payload\n    switch (a.type) {\n        case \"SET_VIEWPORT\":\n            return {\n                ...s,\n                width,\n                height,\n            }\n        default:\n            return s\n    }\n}\n\nexport const tabStateReducer = (s: State.ITabState, a: Actions.SimpleAction): State.ITabState => {\n    switch (a.type) {\n        case \"SET_TABS\":\n            return {\n                ...s,\n                ...a.payload,\n            }\n        default:\n            return s\n    }\n}\n\nexport const buffersReducer = (\n    s: State.IBufferState,\n    a: Actions.SimpleAction,\n): State.IBufferState => {\n    let byId = s.byId\n    let allIds = s.allIds\n\n    const emptyBuffer = (id: number): State.IBuffer => ({\n        id,\n        file: null,\n        modified: false,\n        hidden: true,\n        listed: false,\n        totalLines: 0,\n    })\n\n    switch (a.type) {\n        case \"BUFFER_ENTER\":\n            byId = a.payload.buffers.reduce((buffersById, buffer) => {\n                buffersById[buffer.id] = {\n                    ...buffer,\n                }\n                return byId\n            }, byId)\n\n            const bufIds = a.payload.buffers.map(b => b.id)\n\n            allIds = [...new Set(bufIds)]\n\n            return {\n                activeBufferId: a.payload.buffers[0].id,\n                byId,\n                allIds,\n            }\n        case \"BUFFER_SAVE\":\n            const currentItem = s.byId[a.payload.id] || emptyBuffer(a.payload.id)\n            byId = {\n                ...s.byId,\n                [a.payload.id]: {\n                    ...currentItem,\n                    id: a.payload.id,\n                    modified: a.payload.modified,\n                    lastSaveVersion: a.payload.version,\n                },\n            }\n\n            return {\n                ...s,\n                byId,\n            }\n        case \"BUFFER_UPDATE\":\n            const currentItem3 = s.byId[a.payload.id] || emptyBuffer(a.payload.id)\n\n            // If the last save version hasn't been set, this means it is the first update,\n            // and should clamp to the incoming version\n            const lastSaveVersion = currentItem3.lastSaveVersion || a.payload.version\n\n            byId = {\n                ...s.byId,\n                [a.payload.id]: {\n                    ...currentItem3,\n                    id: a.payload.id,\n                    modified: a.payload.modified,\n                    totalLines: a.payload.totalLines,\n                    lastSaveVersion,\n                },\n            }\n\n            return {\n                ...s,\n                byId,\n            }\n        case \"SET_CURRENT_BUFFERS\":\n            allIds = s.allIds.filter(id => a.payload.bufferIds.indexOf(id) >= 0)\n\n            let activeBufferId = s.activeBufferId\n\n            if (a.payload.bufferIds.indexOf(activeBufferId) === -1) {\n                activeBufferId = null\n            }\n\n            const newById: any = pick(s.byId, a.payload.bufferIds)\n\n            return {\n                activeBufferId,\n                byId: newById,\n                allIds,\n            }\n        default:\n            return s\n    }\n}\n\nexport const errorsReducer = (s: Errors, a: Actions.SimpleAction) => {\n    switch (a.type) {\n        case \"SET_ERRORS\":\n            return {\n                ...a.payload.errors,\n            }\n\n        default:\n            return s\n    }\n}\n\nexport const toolTipsReducer = (s: State.ToolTips, a: Actions.SimpleAction): State.ToolTips => {\n    switch (a.type) {\n        case \"SHOW_TOOL_TIP\":\n            const existingItem = s[a.payload.id] || {}\n            const newItem = {\n                ...existingItem,\n                ...a.payload,\n            }\n\n            return {\n                ...s,\n                [a.payload.id]: newItem,\n            }\n        case \"HIDE_TOOL_TIP\":\n            return {\n                ...s,\n                [a.payload.id]: null,\n            }\n        default:\n            return s\n    }\n}\n\nexport const windowStateReducer = (\n    s: State.IWindowState,\n    a: Actions.SimpleAction,\n): State.IWindowState => {\n    let currentWindow\n    switch (a.type) {\n        case \"SET_WINDOW_CURSOR\":\n            currentWindow = s.windows[a.payload.windowId] || null\n\n            return {\n                activeWindow: a.payload.windowId,\n                windows: {\n                    ...s.windows,\n                    [a.payload.windowId]: {\n                        ...currentWindow,\n                        column: a.payload.column,\n                        line: a.payload.line,\n                    },\n                },\n            }\n        case \"SET_INACTIVE_WINDOW_STATE\":\n            currentWindow = s.windows[a.payload.windowId] || null\n\n            return {\n                ...s,\n                windows: {\n                    ...s.windows,\n                    [a.payload.windowId]: {\n                        ...currentWindow,\n                        windowId: a.payload.windowId,\n                        column: -1,\n                        line: -1,\n                        topBufferLine: -1,\n                        bottomBufferLine: -1,\n                        dimensions: a.payload.dimensions,\n                    },\n                },\n            }\n        case \"SET_WINDOW_STATE\":\n            currentWindow = s.windows[a.payload.windowId] || null\n\n            return {\n                activeWindow: a.payload.windowId,\n                windows: {\n                    ...s.windows,\n                    [a.payload.windowId]: {\n                        ...currentWindow,\n                        file: a.payload.file,\n                        bufferId: a.payload.bufferId,\n                        windowId: a.payload.windowId,\n                        column: a.payload.column,\n                        line: a.payload.line,\n                        bufferToScreen: a.payload.bufferToScreen,\n                        screenToPixel: a.payload.screenToPixel,\n                        bufferToPixel: a.payload.bufferToPixel,\n                        dimensions: a.payload.dimensions,\n\n                        topBufferLine: a.payload.topBufferLine,\n                        bottomBufferLine: a.payload.bottomBufferLine,\n                        visibleLines: a.payload.visibleLines,\n                    },\n                },\n            }\n        default:\n            return s\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditorSelectors.ts",
    "content": "/**\n * Selectors.ts\n *\n * Selectors are basically helper methods for operating on the State\n * See Redux documents here fore more info:\n * http://redux.js.org/docs/recipes/ComputingDerivedData.html\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createSelector } from \"reselect\"\n\nimport { getAllErrorsForFile } from \"./../../Services/Diagnostics\"\nimport * as Utility from \"./../../Utility\"\n\nimport * as State from \"./NeovimEditorStore\"\n\nexport const EmptyArray: any[] = []\n\nconst getWindows = (state: State.IState) => state.windowState\n\nexport const getActiveWindow = createSelector([getWindows], windowState => {\n    if (windowState.activeWindow === null) {\n        return null\n    }\n\n    const activeWindow = windowState.activeWindow\n    return windowState.windows[activeWindow]\n})\n\nconst emptyRectangle: Oni.Shapes.Rectangle = {\n    x: 0,\n    y: 0,\n    width: 0,\n    height: 0,\n}\n\nexport const getFontPixelWidthHeight = (state: State.IState) => ({\n    fontPixelWidth: state.fontPixelWidth,\n    fontPixelHeight: state.fontPixelHeight,\n})\n\nexport const getActiveWindowScreenDimensions = createSelector([getActiveWindow], win => {\n    if (!win || !win.dimensions) {\n        return emptyRectangle\n    }\n\n    return win.dimensions\n})\n\nexport const getActiveWindowPixelDimensions = createSelector(\n    [getActiveWindowScreenDimensions, getFontPixelWidthHeight],\n    (dimensions, fontSize) => {\n        const pixelDimensions = {\n            x: dimensions.x * fontSize.fontPixelWidth,\n            y: dimensions.y * fontSize.fontPixelHeight,\n            width: dimensions.width * fontSize.fontPixelWidth,\n            height: dimensions.height * fontSize.fontPixelHeight,\n        }\n\n        return pixelDimensions\n    },\n)\n\nexport const getErrors = (state: State.IState) => state.errors\n\nexport const getErrorsForActiveFile = createSelector(\n    [getActiveWindow, getErrors],\n    (win, errors) => {\n        const errorsForFile: types.Diagnostic[] =\n            win && win.file\n                ? getAllErrorsForFile(win.file, errors)\n                : (EmptyArray as types.Diagnostic[])\n        return errorsForFile\n    },\n)\n\nexport const getErrorsForPosition = createSelector(\n    [getActiveWindow, getErrorsForActiveFile],\n    (win, errors) => {\n        if (!win) {\n            return EmptyArray\n        }\n\n        const { line, column } = win\n        return errors.filter(diag => Utility.isInRange(line, column, diag.range))\n    },\n)\n\nconst getBufferState = (state: State.IState) => state.buffers\n\nexport const getAllBuffers = createSelector([getBufferState], buffers =>\n    buffers.allIds.map(id => buffers.byId[id]).filter(buf => buf.listed),\n)\n\nexport const getBufferMetadata = createSelector([getAllBuffers], buffers =>\n    buffers.map(b => ({\n        id: b.id,\n        file: b.file,\n        modified: b.modified,\n    })),\n)\n\nexport const getActiveBuffer = createSelector([getActiveWindow, getAllBuffers], (win, buffers) => {\n    if (!win || !win.file) {\n        return null\n    }\n\n    const buf = buffers.find(b => b.file === win.file)\n\n    return buf || null\n})\n\nexport const getActiveBufferId = createSelector(\n    [getActiveBuffer],\n    buf => (buf === null ? null : buf.id),\n)\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimEditorStore.ts",
    "content": "/**\n * State.ts\n *\n * This file describes the Redux state of the app\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport { Store } from \"redux\"\nimport thunk from \"redux-thunk\"\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\n\nimport { DefaultThemeColors, IThemeColors } from \"./../../Services/Themes\"\n\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nimport { IBufferLayer } from \"./../NeovimEditor/BufferLayerManager\"\n\nexport interface Layers {\n    [id: number]: IBufferLayer[]\n}\nexport interface Buffers {\n    [filePath: string]: IBuffer\n}\nexport interface Errors {\n    [file: string]: { [key: string]: types.Diagnostic[] }\n}\nexport interface ToolTips {\n    [id: string]: IToolTip\n}\n\nimport { reducer } from \"./NeovimEditorReducer\"\n\n/**\n * Viewport encompasses the actual 'app' height\n */\nexport interface IViewport {\n    width: number\n    height: number\n}\n\nexport interface IToolTip {\n    id: string\n    options?: Oni.ToolTip.ToolTipOptions\n    element: JSX.Element\n}\n\nexport interface IState {\n    // Editor\n    cursorScale: number\n    cursorPixelX: number\n    cursorPixelY: number\n    cursorPixelWidth: number\n    cursorCharacter: string\n    fontPixelWidth: number\n    fontPixelHeight: number\n    fontFamily: string\n    fontSize: string\n    fontWeight: string\n    hasFocus: boolean\n    mode: string\n    definition: null | IDefinition\n    cursorLineOpacity: number\n    cursorColumnOpacity: number\n    configuration: IConfigurationValues\n    imeActive: boolean\n    isLoaded: boolean\n    viewport: IViewport\n    colors: IThemeColors\n\n    toolTips: ToolTips\n    neovimError: boolean\n\n    /**\n     * Tabs refer to the Vim-concept of tabs\n     */\n    tabState: ITabState\n\n    buffers: IBufferState\n\n    layers: Layers\n\n    windowState: IWindowState\n\n    errors: Errors\n\n    activeVimTabPage: IVimTabPage\n\n    commandLine: ICommandLine | null\n    wildmenu: IWildMenu\n}\n\nexport interface IWildMenu {\n    selected: number\n    visible: boolean\n    options: string[]\n}\n\nexport interface ICommandLine {\n    visible: boolean\n    content: string\n    firstchar: string\n    position: number\n    prompt: string\n    indent: number\n    level: number\n}\n\nexport interface IDefinition {\n    token: Oni.IToken\n    definitionLocation: types.Location\n}\n\nexport interface IBufferState {\n    activeBufferId: number\n    byId: { [id: number]: IBuffer }\n    allIds: number[]\n}\n\nexport interface IBuffer {\n    id: number\n    file: string\n    modified: boolean\n    lastSaveVersion?: number\n    version?: number\n    totalLines: number\n    hidden: boolean\n    listed: boolean\n}\n\nexport interface ITab {\n    id: number\n    name: string\n    buffersInTab: number[]\n}\n\nexport interface ITabState {\n    selectedTabId: number | null\n    tabs: ITab[]\n}\n\nexport interface IVimTabPage {\n    id: number\n    windowIds: number[]\n}\n\nexport interface IWindowState {\n    activeWindow: number\n    windows: { [windowId: number]: IWindow }\n}\n\nexport interface IWindow {\n    file: string\n    bufferId: number\n    windowId: number\n    column: number\n    line: number\n\n    bufferToScreen: Oni.Coordinates.BufferToScreen\n    screenToPixel: Oni.Coordinates.ScreenToPixel\n    bufferToPixel: Oni.Coordinates.BufferToPixel\n\n    dimensions: Oni.Shapes.Rectangle\n    topBufferLine: number\n    bottomBufferLine: number\n\n    visibleLines: string[]\n}\n\nexport function readConf<K extends keyof IConfigurationValues>(\n    conf: IConfigurationValues,\n    k: K,\n): IConfigurationValues[K] {\n    if (!conf) {\n        return null\n    } else {\n        return conf[k]\n    }\n}\n\nexport const createDefaultState = (): IState => ({\n    cursorScale: 1,\n    cursorPixelX: 10,\n    cursorPixelY: 10,\n    cursorPixelWidth: 10,\n    cursorCharacter: \"\",\n    fontPixelWidth: 10,\n    fontPixelHeight: 10,\n    fontFamily: \"\",\n    fontSize: \"\",\n    fontWeight: \"\",\n    hasFocus: false,\n    imeActive: false,\n    mode: \"normal\",\n    definition: null,\n    colors: DefaultThemeColors,\n    cursorLineOpacity: 0,\n    cursorColumnOpacity: 0,\n    neovimError: false,\n    isLoaded: false,\n\n    activeVimTabPage: null,\n\n    configuration: {} as IConfigurationValues,\n\n    buffers: {\n        activeBufferId: null,\n        byId: {},\n        allIds: [],\n    },\n\n    layers: {},\n\n    tabState: {\n        selectedTabId: null,\n        tabs: [],\n    },\n\n    windowState: {\n        activeWindow: null,\n        windows: {},\n    },\n\n    viewport: {\n        width: 0,\n        height: 0,\n    },\n\n    errors: {},\n    toolTips: {},\n    commandLine: {\n        content: null,\n        prompt: null,\n        indent: null,\n        level: null,\n        visible: false,\n        firstchar: \"\",\n        position: 0,\n    },\n    wildmenu: {\n        selected: null,\n        visible: false,\n        options: [],\n    },\n})\n\nlet neovimEditorId = 0\n\nexport const createStore = (): Store<IState> => {\n    const editorId = neovimEditorId++\n    return createReduxStore(\"NeovimEditor\" + editorId.toString(), reducer, createDefaultState(), [\n        thunk,\n    ])\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimInput.tsx",
    "content": "/**\n * NeovimInput.tsx\n *\n * Layer responsible for handling Neovim input interactiosn\n */\n\nimport * as React from \"react\"\n\nimport { IEvent } from \"oni-types\"\n\nimport { Mouse } from \"./../../Input/Mouse\"\nimport { NeovimInstance, NeovimScreen } from \"./../../neovim\"\n\nimport { TypingPredictionManager } from \"./../../Services/TypingPredictionManager\"\n\nimport { KeyboardInput } from \"./../../Input/KeyboardInput\"\n\nexport interface INeovimInputProps {\n    neovimInstance: NeovimInstance\n    screen: NeovimScreen\n    onActivate: IEvent<void>\n    onBounceStart: () => void\n    onBounceEnd: () => void\n    onImeStart: () => void\n    onImeEnd: () => void\n    onKeyDown?: (key: string) => void\n\n    startActive?: boolean\n    typingPrediction: TypingPredictionManager\n}\n\nexport class NeovimInput extends React.PureComponent<INeovimInputProps, {}> {\n    private _mouseElement: HTMLDivElement\n    private _mouse: Mouse\n\n    public componentDidMount(): void {\n        if (this._mouseElement) {\n            this._mouse = new Mouse(this._mouseElement, this.props.screen)\n\n            this._mouse.on(\"mouse\", (mouseInput: string) => {\n                this.props.neovimInstance.input(mouseInput)\n            })\n        }\n    }\n\n    public render(): JSX.Element {\n        return (\n            <div ref={elem => (this._mouseElement = elem)} className=\"stack enable-mouse\">\n                <KeyboardInput\n                    startActive={this.props.startActive}\n                    onActivate={this.props.onActivate}\n                    typingPrediction={this.props.typingPrediction}\n                    onBounceStart={this.props.onBounceStart}\n                    onBounceEnd={this.props.onBounceEnd}\n                    onImeStart={this.props.onImeStart}\n                    onImeEnd={this.props.onImeEnd}\n                    onKeyDown={this.props.onKeyDown}\n                />\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimPopupMenu.tsx",
    "content": "/**\n * NeovimPopupMenu.tsx\n *\n * Implementation of Neovim's popup menu\n */\n\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\nimport { IEvent } from \"oni-types\"\n\nimport { INeovimCompletionInfo, INeovimCompletionItem } from \"./../../neovim\"\nimport { ContextMenuView, IContextMenuItem } from \"./../../Services/ContextMenu\"\n\nimport { IToolTipsProvider } from \"./ToolTipsProvider\"\n\nconst mapNeovimCompletionItemToContextMenuItem = (\n    item: INeovimCompletionItem,\n    idx: number,\n    totalLength: number,\n): IContextMenuItem => ({\n    label: item.word,\n    detail: item.menu,\n    documentation: (idx + 1).toString() + \" of \" + totalLength.toString(),\n    icon: \"align-right\",\n})\n\nexport class NeovimPopupMenu {\n    private _lastItems: IContextMenuItem[] = []\n\n    constructor(\n        private _popupMenuShowEvent: IEvent<INeovimCompletionInfo>,\n        private _popupMenuHideEvent: IEvent<void>,\n        private _popupMenuSelectEvent: IEvent<number>,\n        private _onBufferEnterEvent: IEvent<Oni.EditorBufferEventArgs>,\n        private _toolTipsProvider: IToolTipsProvider,\n    ) {\n        this._popupMenuShowEvent.subscribe(completionInfo => {\n            this._lastItems = completionInfo.items.map((i, idx) =>\n                mapNeovimCompletionItemToContextMenuItem(i, idx, completionInfo.items.length),\n            )\n\n            this._renderCompletionMenu(completionInfo.selectedIndex)\n        })\n\n        this._popupMenuSelectEvent.subscribe(idx => {\n            this._renderCompletionMenu(idx)\n        })\n\n        this._popupMenuHideEvent.subscribe(() => {\n            this._toolTipsProvider.hideToolTip(\"nvim-popup\")\n        })\n\n        this._onBufferEnterEvent.subscribe(() => {\n            this._toolTipsProvider.hideToolTip(\"nvim-popup\")\n        })\n    }\n\n    public dispose(): void {\n        // TODO: Implement 'unsubscribe' logic here\n        // tslint:disable-line\n    }\n\n    private _renderCompletionMenu(selectedIndex: number): void {\n        const itemsToRender: IContextMenuItem[] = this._lastItems\n\n        const completionElement = (\n            <ContextMenuView\n                visible={true}\n                base={\"\"}\n                entries={itemsToRender}\n                selectedIndex={selectedIndex}\n            />\n        )\n\n        this._toolTipsProvider.showToolTip(\"nvim-popup\", completionElement, {\n            position: null,\n            openDirection: 2,\n            padding: \"0px\",\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimRenderer.tsx",
    "content": "/**\n * NeovimRenderer.tsx\n *\n * Layer responsible for invoking the INeovimRender strategy and applying to the DOM\n */\n\nimport * as React from \"react\"\n\nimport { IScreen, NeovimInstance } from \"./../../neovim\"\nimport { INeovimRenderer } from \"./../../Renderer\"\n\nexport interface INeovimRendererProps {\n    neovimInstance: NeovimInstance\n    screen: IScreen\n    renderer: INeovimRenderer\n}\n\nexport class NeovimRenderer extends React.PureComponent<INeovimRendererProps, {}> {\n    private _element: HTMLDivElement\n    private _boundOnResizeMethod: any\n    private _resizeObserver: any\n\n    public componentDidMount(): void {\n        if (this._element) {\n            this.props.renderer.start(this._element)\n\n            this._onResize()\n        }\n\n        if (!this._boundOnResizeMethod) {\n            this._boundOnResizeMethod = this._onResize.bind(this)\n            // tslint:disable-next-line no-string-literal\n            this._resizeObserver = new window[\"ResizeObserver\"]((entries: any) => {\n                if (this._boundOnResizeMethod) {\n                    this._boundOnResizeMethod()\n                }\n            })\n            this._resizeObserver.observe(this._element)\n        }\n    }\n\n    public componentWillUnmount(): void {\n        // TODO: Stop renderer\n\n        if (this._resizeObserver) {\n            this._resizeObserver.disconnect()\n            this._resizeObserver = null\n        }\n\n        if (this._boundOnResizeMethod) {\n            this._boundOnResizeMethod = null\n        }\n    }\n\n    public render(): JSX.Element {\n        return <div ref={elem => (this._element = elem)} className=\"stack layer\" />\n    }\n\n    private _onResize(): void {\n        if (!this._element) {\n            return\n        }\n\n        const width = this._element.offsetWidth\n        const height = this._element.offsetHeight\n\n        this.props.neovimInstance\n            .resize(width, height)\n            .then(() => this.props.renderer.redrawAll(this.props.screen))\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/NeovimSurface.tsx",
    "content": "/**\n * NeovimSurface.tsx\n *\n * UI layer for the Neovim editor surface\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport { IEvent } from \"oni-types\"\n\nimport { NeovimInstance, NeovimScreen } from \"./../../neovim\"\nimport { INeovimRenderer } from \"./../../Renderer\"\nimport FileDropHandler from \"./FileDropHandler\"\n\nimport { TypingPredictionManager } from \"./../../Services/TypingPredictionManager\"\nimport { Cursor } from \"./../../UI/components/Cursor\"\nimport { CursorLine } from \"./../../UI/components/CursorLine\"\nimport { InstallHelp } from \"./../../UI/components/InstallHelp\"\nimport { TabsContainer } from \"./../../UI/components/Tabs\"\nimport { ToolTips } from \"./../../UI/components/ToolTip\"\n\nimport { StackLayer } from \"../../UI/components/common\"\nimport { setViewport } from \"./../NeovimEditor/NeovimEditorActions\"\nimport { NeovimBufferLayers } from \"./NeovimBufferLayersView\"\nimport { NeovimEditorLoadingOverlay } from \"./NeovimEditorLoadingOverlay\"\nimport { NeovimInput } from \"./NeovimInput\"\nimport { NeovimRenderer } from \"./NeovimRenderer\"\n\nexport interface INeovimSurfaceProps {\n    autoFocus: boolean\n    neovimInstance: NeovimInstance\n    renderer: INeovimRenderer\n    screen: NeovimScreen\n    typingPrediction: TypingPredictionManager\n\n    onActivate: IEvent<void>\n\n    onKeyDown?: (key: string) => void\n    onBufferClose?: (bufferId: number) => void\n    onBufferSelect?: (bufferId: number) => void\n    onFileDrop?: (files: FileList) => void\n    onImeStart: () => void\n    onImeEnd: () => void\n    onBounceStart: () => void\n    onBounceEnd: () => void\n    onTabClose?: (tabId: number) => void\n    onTabSelect?: (tabId: number) => void\n    setViewport: any\n}\n\nclass NeovimSurface extends React.Component<INeovimSurfaceProps> {\n    private observer: any\n    private _editor: HTMLDivElement\n\n    public componentDidMount(): void {\n        // tslint:disable-next-line\n        this.observer = new window[\"ResizeObserver\"](([entry]: any) => {\n            this.setDimensions(entry.contentRect.width, entry.contentRect.height)\n        })\n\n        this.observer.observe(this._editor)\n    }\n\n    public setDimensions = (width: number, height: number) => {\n        this.props.setViewport(width, height)\n    }\n\n    public render(): JSX.Element {\n        return (\n            <FileDropHandler handleFiles={this.props.onFileDrop}>\n                {({ setRef }) => (\n                    <div className=\"container vertical full\" ref={setRef}>\n                        <div className=\"container fixed\">\n                            <TabsContainer\n                                onBufferSelect={this.props.onBufferSelect}\n                                onBufferClose={this.props.onBufferClose}\n                                onTabClose={this.props.onTabClose}\n                                onTabSelect={this.props.onTabSelect}\n                            />\n                        </div>\n                        <div className=\"container full\">\n                            <div className=\"stack\" ref={(e: HTMLDivElement) => (this._editor = e)}>\n                                <NeovimRenderer\n                                    renderer={this.props.renderer}\n                                    neovimInstance={this.props.neovimInstance}\n                                    screen={this.props.screen}\n                                />\n                            </div>\n                            <StackLayer>\n                                <Cursor typingPrediction={this.props.typingPrediction} />\n                                <CursorLine lineType={\"line\"} />\n                                <CursorLine lineType={\"column\"} />\n                            </StackLayer>\n                            <NeovimInput\n                                startActive={this.props.autoFocus}\n                                onActivate={this.props.onActivate}\n                                typingPrediction={this.props.typingPrediction}\n                                neovimInstance={this.props.neovimInstance}\n                                screen={this.props.screen}\n                                onBounceStart={this.props.onBounceStart}\n                                onBounceEnd={this.props.onBounceEnd}\n                                onImeStart={this.props.onImeStart}\n                                onImeEnd={this.props.onImeEnd}\n                                onKeyDown={this.props.onKeyDown}\n                            />\n                            <NeovimBufferLayers />\n                            <StackLayer>\n                                <ToolTips />\n                            </StackLayer>\n                            <NeovimEditorLoadingOverlay />\n                            <InstallHelp />\n                        </div>\n                    </div>\n                )}\n            </FileDropHandler>\n        )\n    }\n}\nexport default connect(null, { setViewport })(NeovimSurface)\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/Rename.tsx",
    "content": "/**\n * Rename.tsx\n */\n\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { LanguageManager } from \"./../../Services/Language\"\nimport { RenameView } from \"./../../Services/Language/RenameView\"\nimport { Workspace } from \"./../../Services/Workspace\"\n\nimport { IToolTipsProvider } from \"./ToolTipsProvider\"\n\nconst _renameToolTipName = \"rename-tool-tip\"\nexport class Rename {\n    private _isRenameActive: boolean\n\n    constructor(\n        private _editor: Oni.Editor,\n        private _languageManager: LanguageManager,\n        private _toolTipsProvider: IToolTipsProvider,\n        private _workspace: Workspace,\n    ) {}\n\n    public async startRename(): Promise<void> {\n        if (this._isRenameActive) {\n            return\n        }\n\n        const activeBuffer = this._editor.activeBuffer\n\n        const activeToken = await activeBuffer.getTokenAt(\n            activeBuffer.cursor.line,\n            activeBuffer.cursor.column,\n        )\n\n        if (!activeToken || !activeToken.tokenName) {\n            return\n        }\n\n        this._isRenameActive = true\n\n        this._toolTipsProvider.showToolTip(\n            _renameToolTipName,\n            <RenameView\n                onCancel={() => this.cancelRename()}\n                onComplete={newValue => this.commitRename(newValue)}\n                tokenName={activeToken.tokenName}\n            />,\n            {\n                position: null,\n                openDirection: 2,\n                onDismiss: () => this.cancelRename(),\n            },\n        )\n    }\n\n    public commitRename(newValue: string): void {\n        Log.verbose(\"[RENAME] Committing rename\")\n        this.doRename(newValue)\n        this.closeToolTip()\n    }\n\n    public cancelRename(): void {\n        Log.verbose(\"[RENAME] Cancelling\")\n        this.closeToolTip()\n    }\n\n    public closeToolTip(): void {\n        Log.verbose(\"[RENAME] closeToolTip\")\n        this._isRenameActive = false\n        this._toolTipsProvider.hideToolTip(_renameToolTipName)\n    }\n\n    public async doRename(newName: string): Promise<void> {\n        const activeBuffer = this._editor.activeBuffer\n\n        const args = {\n            textDocument: {\n                uri: Helpers.wrapPathInFileUri(activeBuffer.filePath),\n            },\n            position: {\n                line: activeBuffer.cursor.line,\n                character: activeBuffer.cursor.column,\n            },\n            newName,\n        }\n\n        let result = null\n        try {\n            result = await this._languageManager.sendLanguageServerRequest(\n                activeBuffer.language,\n                activeBuffer.filePath,\n                \"textDocument/rename\",\n                args,\n            )\n        } catch (ex) {\n            Log.debug(ex)\n        }\n\n        if (result) {\n            await this._workspace.applyEdits(result)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/Symbols.ts",
    "content": "/**\n * CodeAction.ts\n *\n */\nimport * as _ from \"lodash\"\nimport { ErrorCodes } from \"vscode-jsonrpc/lib/messages\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { LanguageManager } from \"./../../Services/Language\"\nimport { Menu, MenuManager } from \"./../../Services/Menu\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { asObservable, sleep } from \"./../../Utility\"\n\nimport { Definition } from \"./Definition\"\n\nexport class Symbols {\n    constructor(\n        private _editor: Oni.Editor,\n        private _definition: Definition,\n        private _languageManager: LanguageManager,\n        private _menuManager: MenuManager,\n    ) {}\n\n    public async openWorkspaceSymbolsMenu() {\n        const menu = this._menuManager.create()\n\n        menu.show()\n        menu.setItems([\n            {\n                label: \"Type to search symbols....\",\n            },\n        ])\n        menu.setLoading(true)\n\n        const filterTextChanged$ = asObservable(menu.onFilterTextChanged)\n\n        menu.onItemSelected.subscribe((selectedItem: Oni.Menu.MenuOption) => {\n            const key = selectedItem.label + selectedItem.detail\n\n            const loc = keyToLocation[key]\n\n            if (loc) {\n                this._definition.gotoPositionInUri(\n                    loc.uri,\n                    loc.range.start.line,\n                    loc.range.start.character,\n                )\n            }\n        })\n\n        let keyToLocation: any = {}\n\n        const getKey = (si: types.SymbolInformation) => si.name + this._getDetailFromSymbol(si)\n\n        filterTextChanged$\n            .debounceTime(25)\n            .do(() => menu.setLoading(true))\n            .concatMap(async (newText: string) => {\n                return this._requestSymbols(this._editor.activeBuffer, \"workspace/symbol\", menu, {\n                    query: newText,\n                })\n            })\n            .subscribe((newItems: types.SymbolInformation[]) => {\n                menu.setLoading(false)\n                menu.setItems(newItems.map(item => this._symbolInfoToMenuItem(item)))\n\n                keyToLocation = newItems.reduce((prev, curr) => {\n                    return {\n                        ...prev,\n                        [getKey(curr)]: curr.location,\n                    }\n                }, {})\n            })\n    }\n\n    public async openDocumentSymbolsMenu(): Promise<void> {\n        const menu = this._menuManager.create()\n\n        menu.show()\n        menu.setLoading(true)\n\n        const buffer = this._editor.activeBuffer\n\n        const result: types.SymbolInformation[] = await this._requestSymbols(\n            buffer,\n            \"textDocument/documentSymbol\",\n            menu,\n        )\n\n        const options: Oni.Menu.MenuOption[] = result.map(item => this._symbolInfoToMenuItem(item))\n\n        const labelToLocation = result.reduce((prev, curr) => {\n            return {\n                ...prev,\n                [curr.name]: curr.location,\n            }\n        }, {})\n\n        menu.onItemSelected.subscribe(selectedItem => {\n            const location: types.Location = labelToLocation[selectedItem.label]\n            if (location) {\n                this._definition.gotoPositionInUri(\n                    location.uri,\n                    location.range.start.line,\n                    location.range.start.character,\n                )\n            }\n        })\n\n        menu.setItems(options)\n        menu.setLoading(false)\n    }\n\n    private _getDetailFromSymbol(si: types.SymbolInformation): string {\n        const unwrappedPath = Helpers.unwrapFileUriPath(si.location.uri)\n\n        if (si.containerName) {\n            return si.containerName + \"|\" + unwrappedPath\n        } else {\n            return unwrappedPath\n        }\n    }\n\n    private _symbolInfoToMenuItem(si: types.SymbolInformation): Oni.Menu.MenuOption {\n        return {\n            label: si.name,\n            detail: this._getDetailFromSymbol(si),\n            icon: this._convertSymbolKindToIconName(si.kind),\n        }\n    }\n\n    private _convertSymbolKindToIconName(symbolKind: types.SymbolKind): string {\n        switch (symbolKind) {\n            case types.SymbolKind.Class:\n                return \"cube\"\n            case types.SymbolKind.Constructor:\n                return \"building\"\n            case types.SymbolKind.Enum:\n                return \"sitemap\"\n            case types.SymbolKind.Field:\n                return \"var\"\n            case types.SymbolKind.File:\n                return \"file\"\n            case types.SymbolKind.Function:\n                return \"cog\"\n            case types.SymbolKind.Interface:\n                return \"plug\"\n            case types.SymbolKind.Method:\n                return \"flash\"\n            case types.SymbolKind.Module:\n                return \"cubes\"\n            case types.SymbolKind.Property:\n                return \"wrench\"\n            case types.SymbolKind.Variable:\n                return \"code\"\n            default:\n                return \"question\"\n        }\n    }\n\n    /**\n     * Send a request for symbols, retrying if the server is not ready, as long as the menu is open.\n     */\n    private async _requestSymbols(\n        buffer: Oni.Buffer,\n        command: string,\n        menu: Menu,\n        options: any = {},\n    ): Promise<types.SymbolInformation[]> {\n        while (menu.isOpen()) {\n            try {\n                return await this._languageManager.sendLanguageServerRequest(\n                    buffer.language,\n                    buffer.filePath,\n                    command,\n                    _.extend(\n                        {\n                            textDocument: {\n                                uri: Helpers.wrapPathInFileUri(buffer.filePath),\n                            },\n                        },\n                        options,\n                    ),\n                )\n            } catch (e) {\n                if (e.code === ErrorCodes.ServerNotInitialized) {\n                    Log.warn(\"[Symbols] Language server not yet initialised, trying again...\")\n                    await sleep(1000)\n                } else {\n                    throw e\n                }\n            }\n        }\n        return []\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/ToolTipsProvider.ts",
    "content": "import * as Oni from \"oni-api\"\n\nimport * as Actions from \"./NeovimEditorActions\"\n\nexport interface IToolTipsProvider {\n    showToolTip(id: string, element: JSX.Element, options: Oni.ToolTip.ToolTipOptions): void\n    hideToolTip(id: string): void\n}\n\nexport class NeovimEditorToolTipsProvider implements IToolTipsProvider {\n    constructor(private _actions: typeof Actions) {}\n\n    public showToolTip(\n        id: string,\n        element: JSX.Element,\n        options: Oni.ToolTip.ToolTipOptions,\n    ): void {\n        this._actions.showToolTip(id, element, options)\n    }\n\n    public hideToolTip(id: string): void {\n        this._actions.hideToolTip(id)\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/WelcomeBufferLayer.tsx",
    "content": "/**\n * NeovimEditor.ts\n *\n * IEditor implementation for Neovim\n */\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event } from \"oni-types\"\nimport * as React from \"react\"\n\nimport { getMetadata } from \"./../../Services/Metadata\"\nimport { ISession, SessionManager } from \"./../../Services/Sessions\"\nimport styled, {\n    boxShadowInset,\n    Css,\n    css,\n    enableMouse,\n    getSelectedBorder,\n    keyframes,\n    lighten,\n} from \"./../../UI/components/common\"\nimport { Icon } from \"./../../UI/Icon\"\n\n// const entrance = keyframes`\n//     0% { opacity: 0; transform: translateY(2px); }\n//     100% { opacity: 0.5; transform: translateY(0px); }\n// `\n\n// const enterLeft = keyframes`\n//     0% { opacity: 0; transform: translateX(-4px); }\n//     100% { opacity: 1; transform: translateX(0px); }\n// `\n\n// const enterRight = keyframes`\n//     0% { opacity: 0; transform: translateX(4px); }\n//     100% { opacity: 1; transform: translateX(0px); }\n// `\n\nconst entranceFull = keyframes`\n    0% {\n        opacity: 0;\n        transform: translateY(8px);\n    }\n    100% {\n        opacity: 1;\n        transform: translateY(0px);\n    }\n`\nconst WelcomeWrapper = styled.div`\n    background-color: ${p => p.theme[\"editor.background\"]};\n    color: ${p => p.theme[\"editor.foreground\"]};\n    overflow-y: hidden;\n    user-select: none;\n    pointer-events: all;\n    width: 100%;\n    height: 100%;\n    opacity: 0;\n    animation: ${entranceFull} 0.25s ease-in 0.1s forwards ${enableMouse};\n`\n\ninterface IColumnProps {\n    alignment?: string\n    justify?: string\n    flex?: string\n    height?: string\n    extension?: Css\n}\n\nconst Column = styled<IColumnProps, \"div\">(\"div\")`\n    background: inherit;\n    display: flex;\n    justify-content: ${({ justify }) => justify || `center`};\n    align-items: ${({ alignment }) => alignment || \"center\"};\n    flex-direction: column;\n    width: 100%;\n    flex: ${({ flex }) => flex || \"1\"};\n    height: ${({ height }) => height || `auto`};\n    ${({ extension }) => extension};\n`\n\nconst sectionStyles = css`\n    display: flex;\n    flex-direction: column;\n    justify-content: flex-start;\n    align-items: center;\n    height: 90%;\n    overflow-y: hidden;\n    direction: rtl;\n    &:hover {\n        overflow-y: overlay;\n    }\n    & > * {\n        direction: ltr;\n    }\n`\n\nconst LeftColumn = styled.div`\n    ${sectionStyles};\n    padding: 0;\n    padding-left: 1rem;\n    overflow-y: hidden;\n    width: 60%;\n`\n\nconst RightColumn = styled.div`\n    ${sectionStyles};\n    width: 30%;\n    border-left: 1px solid ${({ theme }) => theme[\"editor.background\"]};\n`\n\nconst Row = styled<{ extension?: Css }, \"div\">(\"div\")`\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    flex-direction: row;\n    opacity: 0;\n    ${({ extension }) => extension};\n`\n\nconst TitleText = styled.div`\n    font-size: 2em;\n    text-align: right;\n`\n\nconst SubtitleText = styled.div`\n    font-size: 1.2em;\n    text-align: right;\n`\n\nconst HeroImage = styled.img`\n    width: 192px;\n    height: 192px;\n    opacity: 0.4;\n`\n\nexport const SectionHeader = styled.div`\n    margin-top: 1em;\n    margin-bottom: 1em;\n    font-size: 1.2em;\n    font-weight: bold;\n    text-align: left;\n    width: 100%;\n`\n\nconst WelcomeButtonHoverStyled = `\n    transform: translateY(-1px);\n    box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n`\n\nexport interface WelcomeButtonWrapperProps {\n    isSelected: boolean\n    borderSize: string\n}\n\nconst WelcomeButtonWrapper = styled<WelcomeButtonWrapperProps, \"button\">(\"button\")`\n    box-sizing: border-box;\n    font-size: inherit;\n    font-family: inherit;\n    border: 0px solid ${props => props.theme.foreground};\n    border-left: ${getSelectedBorder};\n    border-right: 4px solid transparent;\n    cursor: pointer;\n    color: ${({ theme }) => theme.foreground};\n    background-color: ${({ theme }) => lighten(theme.background)};\n    transform: ${({ isSelected }) => (isSelected ? \"translateX(-4px)\" : \"translateX(0px)\")};\n    transition: transform 0.25s;\n    width: 100%;\n    margin: 0.8em 0;\n    padding: 0.8em;\n    display: flex;\n    flex-direction: row;\n    &:hover {\n        ${WelcomeButtonHoverStyled};\n    }\n`\n\nconst AnimatedContainer = styled<{ duration: string }, \"div\">(\"div\")`\n    width: 100%;\n    animation: ${entranceFull} ${p => p.duration} ease-in 1s both;\n`\n\nconst WelcomeButtonTitle = styled.span`\n    font-size: 1em;\n    font-weight: bold;\n    margin: 0.4em;\n    width: 100%;\n    text-align: left;\n`\n\nconst WelcomeButtonDescription = styled.span`\n    font-size: 0.8em;\n    opacity: 0.75;\n    margin: 4px;\n    width: 100%;\n    text-align: right;\n`\n\nconst boxStyling = css`\n    width: 60%;\n    height: 60%;\n    padding: 0 1em;\n    opacity: 1;\n    margin-top: 64px;\n    box-sizing: border-box;\n    border: 1px solid ${p => p.theme[\"editor.hover.contents.background\"]};\n    border-radius: 4px;\n    overflow: hidden;\n    justify-content: space-around;\n    background-color: ${p => p.theme[\"editor.hover.contents.codeblock.background\"]};\n    ${boxShadowInset};\n`\n\nconst titleRow = css`\n    width: 100%;\n    padding-top: 32px;\n    animation: ${entranceFull} 0.25s ease-in 0.25s forwards};\n`\n\nconst selectedSectionItem = css`\n    ${({ theme }) => `\n        text-decoration: underline;\n        color: ${theme[\"highlight.mode.normal.background\"]};\n    `};\n`\n\nexport const SectionItem = styled<{ isSelected?: boolean }, \"li\">(\"li\")`\n    width: 100%;\n    margin: 0.2em;\n    text-align: left;\n    height: auto;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    ${({ isSelected }) => isSelected && selectedSectionItem};\n\n    &:hover {\n        text-decoration: underline;\n    }\n`\n\nexport const SessionsList = styled.ul`\n    width: 70%;\n    margin: 0;\n    list-style-type: none;\n    border-radius: 4px;\n    padding: 0 1em;\n    border: 1px solid ${p => p.theme[\"editor.hover.contents.codeblock.background\"]};\n`\n\nexport interface WelcomeButtonProps {\n    title: string\n    description: string\n    command: string\n    selected: boolean\n    onClick: () => void\n}\n\ninterface IChromeDiv extends HTMLButtonElement {\n    scrollIntoViewIfNeeded: () => void\n}\n\nexport class WelcomeButton extends React.PureComponent<WelcomeButtonProps> {\n    private _button = React.createRef<IChromeDiv>()\n\n    public componentDidUpdate(prevProps: WelcomeButtonProps) {\n        if (!prevProps.selected && this.props.selected) {\n            this._button.current.scrollIntoViewIfNeeded()\n        }\n    }\n\n    public render() {\n        return (\n            <WelcomeButtonWrapper\n                borderSize=\"4px\"\n                innerRef={this._button}\n                isSelected={this.props.selected}\n                onClick={this.props.onClick}\n            >\n                <WelcomeButtonTitle>{this.props.title}</WelcomeButtonTitle>\n                <WelcomeButtonDescription>{this.props.description}</WelcomeButtonDescription>\n            </WelcomeButtonWrapper>\n        )\n    }\n}\n\nexport interface WelcomeHeaderState {\n    version: string\n}\n\nexport interface OniWithActiveSection extends Oni.Plugin.Api {\n    sessions: SessionManager\n    getActiveSection(): string\n}\n\ntype ExecuteCommand = <T>(command: string, args?: T) => void\n\nexport interface IWelcomeInputEvent {\n    select: boolean\n    vertical: number\n    horizontal?: number\n}\n\ninterface ICommandMetadata {\n    execute: <T = undefined>(args?: T) => void\n    command: string\n}\n\nexport interface IWelcomeCommandsDictionary {\n    openFile: ICommandMetadata\n    openTutor: ICommandMetadata\n    openDocs: ICommandMetadata\n    openConfig: ICommandMetadata\n    openThemes: ICommandMetadata\n    openWorkspaceFolder: ICommandMetadata\n    commandPalette: ICommandMetadata\n    commandline: ICommandMetadata\n    restoreSession: (sessionName: string) => Promise<void>\n}\n\nexport class WelcomeBufferLayer implements Oni.BufferLayer {\n    public inputEvent = new Event<IWelcomeInputEvent>()\n\n    constructor(private _oni: OniWithActiveSection) {}\n\n    public showCommandline = async () => {\n        const remapping: string = await this._oni.editors.activeEditor.neovim.callFunction(\n            \"mapcheck\",\n            [\":\", \"n\"],\n        )\n        const mapping = remapping || \":\"\n        this._oni.automation.sendKeys(mapping)\n    }\n\n    public executeCommand: ExecuteCommand = (cmd, args) => {\n        this._oni.commands.executeCommand(cmd, args)\n    }\n\n    public restoreSession = async (name: string) => {\n        await this._oni.sessions.restoreSession(name)\n    }\n\n    // tslint:disable-next-line\n    public readonly welcomeCommands: IWelcomeCommandsDictionary = {\n        openFile: {\n            execute: args => this.executeCommand(\"oni.editor.newFile\", args),\n            command: \"oni.editor.newFile\",\n        },\n        openWorkspaceFolder: {\n            execute: args => this.executeCommand(\"workspace.openFolder\", args),\n            command: \"workspace.openFolder\",\n        },\n        commandPalette: {\n            execute: args => this.executeCommand(\"commands.show\", args),\n            command: \"commands.show\",\n        },\n        commandline: {\n            execute: this.showCommandline,\n            command: \"editor.executeVimCommand\",\n        },\n        openTutor: {\n            execute: args => this.executeCommand(\"oni.tutor.open\", args),\n            command: \"oni.tutor.open\",\n        },\n        openDocs: {\n            execute: args => this.executeCommand(\"oni.docs.open\", args),\n            command: \"oni.docs.open\",\n        },\n        openConfig: {\n            execute: args => this.executeCommand(\"oni.config.openUserConfig\", args),\n            command: \"oni.config.openUserConfig\",\n        },\n        openThemes: {\n            execute: args => this.executeCommand(\"oni.themes.choose\", args),\n            command: \"oni.themes.open\",\n        },\n        restoreSession: args => this.restoreSession(args),\n    }\n\n    public get id() {\n        return \"oni.welcome\"\n    }\n\n    public get friendlyName() {\n        return \"Welcome\"\n    }\n\n    public isActive(): boolean {\n        const activeSection = this._oni.getActiveSection()\n        return activeSection === \"editor\"\n    }\n\n    public handleInput(key: string) {\n        Log.info(`ONI WELCOME INPUT KEY: ${key}`)\n        switch (key) {\n            case \"j\":\n                this.inputEvent.dispatch({ vertical: 1, select: false })\n                break\n            case \"k\":\n                this.inputEvent.dispatch({ vertical: -1, select: false })\n                break\n            case \"l\":\n                this.inputEvent.dispatch({ vertical: 0, select: false, horizontal: 1 })\n                break\n            case \"h\":\n                this.inputEvent.dispatch({ vertical: 0, select: false, horizontal: -1 })\n                break\n            case \"<enter>\":\n                this.inputEvent.dispatch({ vertical: 0, select: true })\n                break\n            default:\n                this.inputEvent.dispatch({ vertical: 0, select: false })\n        }\n    }\n\n    public getProps() {\n        const active = this._oni.getActiveSection() === \"editor\"\n        const commandIds = Object.values(this.welcomeCommands)\n            .map(({ command }) => command)\n            .filter(Boolean)\n\n        const sessions = this._oni.sessions ? this._oni.sessions.allSessions : ([] as ISession[])\n        const sessionIds = sessions.map(({ id }) => id)\n        const ids = [...commandIds, ...sessionIds]\n        const sections = [commandIds.length, sessionIds.length].filter(Boolean)\n\n        return { active, ids, sections, sessions }\n    }\n\n    public render(context: Oni.BufferLayerRenderContext) {\n        const props = this.getProps()\n        return (\n            <WelcomeWrapper>\n                <WelcomeView\n                    {...props}\n                    getMetadata={getMetadata}\n                    inputEvent={this.inputEvent}\n                    commands={this.welcomeCommands}\n                    restoreSession={this.restoreSession}\n                    executeCommand={this.executeCommand}\n                />\n            </WelcomeWrapper>\n        )\n    }\n}\n\nexport interface WelcomeViewProps {\n    active: boolean\n    sessions: ISession[]\n    sections: number[]\n    ids: string[]\n    inputEvent: Event<IWelcomeInputEvent>\n    commands: IWelcomeCommandsDictionary\n    getMetadata: () => Promise<{ version: string }>\n    restoreSession: (name: string) => Promise<void>\n    executeCommand: ExecuteCommand\n}\n\nexport interface WelcomeViewState {\n    version: string\n    selectedId: string\n    currentIndex: number\n}\n\nexport class WelcomeView extends React.PureComponent<WelcomeViewProps, WelcomeViewState> {\n    public state: WelcomeViewState = {\n        version: null,\n        currentIndex: 0,\n        selectedId: this.props.ids[0],\n    }\n\n    private _welcomeElement = React.createRef<HTMLDivElement>()\n\n    public async componentDidMount() {\n        const metadata = await this.props.getMetadata()\n        this.setState({ version: metadata.version })\n        this.props.inputEvent.subscribe(this.handleInput)\n    }\n\n    public handleInput = async ({ vertical, select, horizontal }: IWelcomeInputEvent) => {\n        const { currentIndex } = this.state\n        const { sections, ids, active } = this.props\n\n        const newIndex = this.getNextIndex(currentIndex, vertical, horizontal, sections)\n        const selectedId = ids[newIndex]\n        this.setState({ currentIndex: newIndex, selectedId })\n\n        const selectedSession = this.props.sessions.find(session => session.id === selectedId)\n\n        if (select && active) {\n            if (selectedSession) {\n                await this.props.commands.restoreSession(selectedSession.name)\n            } else {\n                const currentCommand = this.getCurrentCommand(selectedId)\n                currentCommand.execute()\n            }\n        }\n    }\n\n    public getCurrentCommand(selectedId: string): ICommandMetadata {\n        const { commands } = this.props\n        const currentCommand = Object.values(commands).find(({ command }) => command === selectedId)\n        return currentCommand\n    }\n\n    public getNextIndex(\n        currentIndex: number,\n        vertical: number,\n        horizontal: number,\n        sections: number[],\n    ) {\n        const nextPosition = currentIndex + vertical\n        const numberOfItems = this.props.ids.length\n        const multipleSections = sections.length > 1\n\n        // TODO: this currently handles *TWO* sections if more sections\n        // are to be added will need to rethink how to allow navigation across multiple sections\n        switch (true) {\n            case multipleSections && horizontal === 1:\n                return sections[0]\n            case multipleSections && horizontal === -1:\n                return 0\n            case nextPosition < 0:\n                return numberOfItems - 1\n            case nextPosition === numberOfItems:\n                return 0\n            default:\n                return nextPosition\n        }\n    }\n\n    public componentDidUpdate() {\n        if (this.props.active && this._welcomeElement && this._welcomeElement.current) {\n            this._welcomeElement.current.focus()\n        }\n    }\n\n    public render() {\n        const { version, selectedId } = this.state\n        return (\n            <Column innerRef={this._welcomeElement} height=\"100%\" data-id=\"welcome-screen\">\n                <Row extension={titleRow}>\n                    <Column />\n                    <Column alignment=\"flex-end\">\n                        <TitleText>Oni</TitleText>\n                        <SubtitleText>Modern Modal Editing</SubtitleText>\n                    </Column>\n                    <Column flex=\"0 0\">\n                        <HeroImage src=\"images/oni-icon-no-border.svg\" />\n                    </Column>\n                    <Column alignment=\"flex-start\">\n                        {version && <SubtitleText>{`v${version}`}</SubtitleText>}\n                        <div>{\"https://onivim.io\"}</div>\n                    </Column>\n                    <Column />\n                </Row>\n                <Row extension={boxStyling}>\n                    <WelcomeCommandsView\n                        commands={this.props.commands}\n                        selectedId={selectedId}\n                        executeCommand={this.props.executeCommand}\n                    />\n                    <RightColumn>\n                        <SessionsList>\n                            <SectionHeader>Sessions</SectionHeader>\n                            {this.props.sessions.length ? (\n                                this.props.sessions.map(session => (\n                                    <SectionItem\n                                        isSelected={session.id === selectedId}\n                                        onClick={() => this.props.restoreSession(session.name)}\n                                        key={session.id}\n                                    >\n                                        <Icon name=\"file\" style={{ marginRight: \"0.3em\" }} />{\" \"}\n                                        {session.name}\n                                    </SectionItem>\n                                ))\n                            ) : (\n                                <SectionItem>No Sessions Available</SectionItem>\n                            )}\n                        </SessionsList>\n                    </RightColumn>\n                </Row>\n            </Column>\n        )\n    }\n}\n\nexport interface IWelcomeCommandsViewProps extends Partial<WelcomeViewProps> {\n    selectedId: string\n}\n\nexport const WelcomeCommandsView: React.SFC<IWelcomeCommandsViewProps> = props => {\n    const isSelected = (command: string) => command === props.selectedId\n    const { commands } = props\n    return (\n        <LeftColumn>\n            <AnimatedContainer duration=\"0.25s\">\n                <SectionHeader>Quick Commands</SectionHeader>\n                <WelcomeButton\n                    title=\"New File\"\n                    onClick={() => commands.openFile.execute()}\n                    description=\"Control + N\"\n                    command={commands.openFile.command}\n                    selected={isSelected(commands.openFile.command)}\n                />\n                <WelcomeButton\n                    title=\"Open File / Folder\"\n                    description=\"Control + O\"\n                    onClick={() => commands.openWorkspaceFolder.execute()}\n                    command={commands.openWorkspaceFolder.command}\n                    selected={isSelected(commands.openWorkspaceFolder.command)}\n                />\n                <WelcomeButton\n                    title=\"Command Palette\"\n                    onClick={() => commands.commandPalette.execute()}\n                    description=\"Control + Shift + P\"\n                    command={commands.commandPalette.command}\n                    selected={isSelected(commands.commandPalette.command)}\n                />\n                <WelcomeButton\n                    title=\"Vim Ex Commands\"\n                    description=\":\"\n                    command=\"editor.openExCommands\"\n                    onClick={() => commands.commandline.execute()}\n                    selected={isSelected(commands.commandline.command)}\n                />\n            </AnimatedContainer>\n            <AnimatedContainer duration=\"0.25s\">\n                <SectionHeader>Learn</SectionHeader>\n                <WelcomeButton\n                    title=\"Tutor\"\n                    onClick={() => commands.openTutor.execute()}\n                    description=\"Learn modal editing with an interactive tutorial.\"\n                    command={commands.openTutor.command}\n                    selected={isSelected(commands.openTutor.command)}\n                />\n                <WelcomeButton\n                    title=\"Documentation\"\n                    onClick={() => commands.openDocs.execute()}\n                    description=\"Discover what Oni can do for you.\"\n                    command={commands.openDocs.command}\n                    selected={isSelected(commands.openDocs.command)}\n                />\n            </AnimatedContainer>\n            <AnimatedContainer duration=\"0.25s\">\n                <SectionHeader>Customize</SectionHeader>\n                <WelcomeButton\n                    title=\"Configure\"\n                    onClick={() => commands.openConfig.execute()}\n                    description=\"Make Oni work the way you want.\"\n                    command={commands.openConfig.command}\n                    selected={isSelected(commands.openConfig.command)}\n                />\n                <WelcomeButton\n                    title=\"Themes\"\n                    onClick={() => commands.openThemes.execute()}\n                    description=\"Choose a theme that works for you.\"\n                    command={commands.openThemes.command}\n                    selected={isSelected(commands.openThemes.command)}\n                />\n            </AnimatedContainer>\n        </LeftColumn>\n    )\n}\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/index.ts",
    "content": "export * from \"./NeovimEditor\"\n"
  },
  {
    "path": "browser/src/Editor/NeovimEditor/markdown.ts",
    "content": "import { unescape } from \"lodash\"\nimport * as marked from \"marked\"\n\nimport * as Log from \"oni-core-logging\"\nimport { IGrammarPerLine, IGrammarToken } from \"./../../Services/SyntaxHighlighting/TokenGenerator\"\n\nimport * as DOMPurify from \"dompurify\"\n\nconst renderer = new marked.Renderer()\ninterface IRendererArgs {\n    tokens?: IGrammarPerLine\n    text: string\n    element?: TextElement\n    container?: TextElement\n}\n\ninterface Symbols {\n    [symbol: string]: string[]\n}\n\nexport const scopesToString = (scope: string[]) => {\n    if (scope) {\n        return scope\n            .map(s => {\n                if (s.includes(\".\")) {\n                    const lastStop = s.lastIndexOf(\".\")\n                    const remainder = s.substring(0, lastStop)\n                    return remainder.replace(/\\./g, \"-\")\n                }\n                return s\n            })\n            .filter(value => !!value)\n            .join(\" \")\n    }\n    return null\n}\n\n/**\n * escapeRegExp\n * Escapes a string intended for use as a regexp\n * @param {string} str\n * @returns {string}\n */\nexport function escapeRegExp(str: string) {\n    // NOTE This does NOT escape the \"|\" operator as it's needed for the Reg Exp\n    // Also does not escape \"\\-\" as hypenated tokens can be found\n    return str.replace(/[\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\n\\r]/g, \"\\\\$&\")\n}\n\ntype TextElement = \"code\" | \"pre\" | \"p\" | \"span\"\nexport const createContainer = (type: TextElement, content: string) => {\n    switch (type) {\n        case \"pre\":\n            return `<pre class=\"marked-pre\">${content}</pre>`\n        case \"p\":\n            return `<${type} class=\"marked-paragraph\">${content}</${type}>`\n        case \"code\":\n        default:\n            return content\n    }\n}\n\ninterface WrapTokenArgs {\n    tokens: IGrammarToken[]\n    element: string\n    text: string\n}\nexport function wrapTokens({ tokens, element, text }: WrapTokenArgs): string {\n    try {\n        const symbols: Symbols = tokens.reduce((acc, token) => {\n            const symbol = text.substring(token.range.start.character, token.range.end.character)\n            acc[symbol] = token.scopes\n            return acc\n        }, {})\n\n        const symbolNames = Object.keys(symbols)\n        const banned = [\"\\n\", \"\\r\", \" \", \"|\"]\n        const filteredNames = symbolNames.filter(str => !banned.includes(str))\n        // Check if a word is alphabetical if so make sure to match full words only\n        // if not alphabetical escape the string\n        const wholeWordMatch = filteredNames.map(\n            str => (/^[A-Za-z]/.test(str) ? `\\\\b${str}\\\\b` : escapeRegExp(str)),\n        )\n        const symbolRegex = new RegExp(\"(\" + wholeWordMatch.join(\"|\") + \")\", \"g\")\n        const html = text.replace(symbolRegex, (match, ...args) => {\n            const className = scopesToString(symbols[match])\n            return `<${element} class=\"marked ${className}\">${match}</${element}>`\n        })\n        return html\n    } catch (e) {\n        Log.warn(`Regex construction failed with: ${e.message}`)\n        return text\n    }\n}\n\n/**\n * Takes a list of tokens which contain ranges, the text from marked (3rd party lib)\n * uses a reg exp to replace all matching tokens with an element with a class that is styled\n * else where\n * @returns {string}\n */\nexport function renderWithClasses({\n    tokens,\n    text,\n    element = \"span\",\n    container = \"p\",\n}: IRendererArgs) {\n    // This is critical because marked's renderer refuses to leave html untouched so it converts\n    // special chars to html entities\n    const unescapedText = unescape(text)\n    const whiteSpaceForCode = (line: string, code: boolean) => (code ? line.trim() : line)\n\n    if (tokens) {\n        const isCodeBlock = container === \"code\"\n        const tokenValues = Object.values(tokens)\n        const tokenLines = tokenValues.map(l => whiteSpaceForCode(l.line, isCodeBlock))\n        const parts = unescapedText.split(\"\\n\")\n        // Find common lines in lines to render and lines in tokenisation map\n        const intersection = tokenLines.filter(x => parts.includes(x))\n        const lineToToken = tokenValues.reduce((acc, t) => {\n            const key = whiteSpaceForCode(t.line, isCodeBlock)\n            acc[key] = t\n            return acc\n        }, {})\n        if (intersection.length) {\n            const html = intersection.reduce((acc, match) => {\n                return `${(acc += wrapTokens({\n                    tokens: lineToToken[match].tokens,\n                    element,\n                    text: lineToToken[match].line,\n                }))}\\n`\n            }, \"\")\n            if (container) {\n                return createContainer(container, html)\n            }\n            return html\n        }\n    }\n    return text\n}\n\ninterface IConversionArgs {\n    markdown: string\n    tokens?: IGrammarPerLine\n    type?: string\n}\n\nconst config = {\n    FORBID_TAGS: [\"img\", \"script\"],\n}\n\n/**\n * Takes a markdown string and defines a custom renderer then for the element type and returns an html string\n *\n * @name convertMarkdown\n * @function\n * @param {string} {markdown A Markdown String\n * @param {Object} tokens An Object of lines with tokens for each line\n * @param {string} type the section of the quickfix being processed\n * @returns {string} An html string\n */\nexport const convertMarkdown = ({ markdown, tokens, type = \"title\" }: IConversionArgs): string => {\n    marked.setOptions({\n        sanitize: true,\n        gfm: true,\n        renderer,\n        highlight: (code, lang) => {\n            return renderWithClasses({ text: code, tokens, container: \"code\" })\n        },\n    })\n\n    switch (type) {\n        case \"documentation\":\n            renderer.html = htmlString => DOMPurify.sanitize(htmlString, config)\n            renderer.paragraph = text => createContainer(\"p\", DOMPurify.sanitize(text, config))\n\n            break\n        case \"title\":\n        default:\n            renderer.html = htmlString => DOMPurify.sanitize(htmlString, config)\n            renderer.paragraph = text => {\n                const stringWithClasses = renderWithClasses({ text, tokens })\n                return DOMPurify.sanitize(stringWithClasses, config)\n            }\n            renderer.blockquote = text => {\n                const stringWithClasses = renderWithClasses({\n                    text,\n                    tokens,\n                    container: \"pre\",\n                })\n                return DOMPurify.sanitize(stringWithClasses, config)\n            }\n    }\n\n    const html = marked(markdown)\n    return html\n}\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/ColorHighlightLayer.tsx",
    "content": "import * as Color from \"color\"\nimport * as memoize from \"lodash/memoize\"\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport * as React from \"react\"\n\nimport styled, { pixel, withProps } from \"../../UI/components/common\"\n\ninterface IBackground {\n    top: number\n    left: number\n    height: number\n    width: number\n}\n\ninterface IHighlight {\n    color: string\n    fontFamily: string\n    height: number\n    fontSize: string\n}\n\nconst Background = withProps<IBackground>(styled.div).attrs({\n    style: (props: IBackground) => ({\n        top: pixel(props.top),\n        left: pixel(props.left),\n        height: pixel(props.height),\n        width: pixel(props.width),\n    }),\n})`\n    background-color: ${p => p.theme[\"editor.background\"]};\n    position: absolute;\n    white-space: nowrap;\n`\n\nconst HighlightSpan = withProps<IHighlight>(styled.div)`\n    display: block;\n    height: 100%;\n    width: 100%;\n    color: ${p => (Color(p.color).dark() ? \"white\" : \"black\")};\n    font-family: ${p => p.fontFamily};\n    font-size: ${p => p.fontSize};\n    line-height: ${p => pixel(p.height + 5)}; /* vertically center text inside the highlight */\n    background-color: ${p => p.color};\n`\n\ninterface IState {\n    error: Error\n}\n\ntype IProps = IHighlight & IBackground\n\nclass Highlight extends React.PureComponent<IProps, IState> {\n    public state: IState = {\n        error: null,\n    }\n\n    public componentDidCatch(error: Error) {\n        this.setState({ error })\n    }\n\n    public render() {\n        return (\n            !this.state.error && (\n                <Background\n                    top={this.props.top}\n                    left={this.props.left}\n                    height={this.props.height}\n                    width={this.props.width}\n                    data-id=\"color-highlight\"\n                >\n                    <HighlightSpan\n                        fontFamily={this.props.fontFamily}\n                        fontSize={this.props.fontSize}\n                        height={this.props.height}\n                        color={this.props.color}\n                    >\n                        {this.props.children}\n                    </HighlightSpan>\n                </Background>\n            )\n        )\n    }\n}\n\nexport default class ColorHighlightLayer implements Oni.BufferLayer {\n    public render = memoize((context: Oni.BufferLayerRenderContext) => (\n        <>{this._getColorHighlights(context)}</>\n    ))\n\n    private readonly CSS_COLOR_NAMES = [\n        \"AliceBlue\",\n        \"AntiqueWhite\",\n        \"Aqua\",\n        \"Aquamarine\",\n        \"Azure\",\n        \"Beige\",\n        \"Bisque\",\n        \"Black\",\n        \"BlanchedAlmond\",\n        \"Blue\",\n        \"BlueViolet\",\n        \"Brown\",\n        \"BurlyWood\",\n        \"CadetBlue\",\n        \"Chartreuse\",\n        \"Chocolate\",\n        \"Coral\",\n        \"CornflowerBlue\",\n        \"Cornsilk\",\n        \"Crimson\",\n        \"Cyan\",\n        \"DarkBlue\",\n        \"DarkCyan\",\n        \"DarkGoldenRod\",\n        \"DarkGray\",\n        \"DarkGrey\",\n        \"DarkGreen\",\n        \"DarkKhaki\",\n        \"DarkMagenta\",\n        \"DarkOliveGreen\",\n        \"Darkorange\",\n        \"DarkOrchid\",\n        \"DarkRed\",\n        \"DarkSalmon\",\n        \"DarkSeaGreen\",\n        \"DarkSlateBlue\",\n        \"DarkSlateGray\",\n        \"DarkSlateGrey\",\n        \"DarkTurquoise\",\n        \"DarkViolet\",\n        \"DeepPink\",\n        \"DeepSkyBlue\",\n        \"DimGray\",\n        \"DimGrey\",\n        \"DodgerBlue\",\n        \"FireBrick\",\n        \"FloralWhite\",\n        \"ForestGreen\",\n        \"Fuchsia\",\n        \"Gainsboro\",\n        \"GhostWhite\",\n        \"Gold\",\n        \"GoldenRod\",\n        \"Gray\",\n        \"Grey\",\n        \"Green\",\n        \"GreenYellow\",\n        \"HoneyDew\",\n        \"HotPink\",\n        \"IndianRed\",\n        \"Indigo\",\n        \"Ivory\",\n        \"Khaki\",\n        \"Lavender\",\n        \"LavenderBlush\",\n        \"LawnGreen\",\n        \"LemonChiffon\",\n        \"LightBlue\",\n        \"LightCoral\",\n        \"LightCyan\",\n        \"LightGoldenRodYellow\",\n        \"LightGray\",\n        \"LightGrey\",\n        \"LightGreen\",\n        \"LightPink\",\n        \"LightSalmon\",\n        \"LightSeaGreen\",\n        \"LightSkyBlue\",\n        \"LightSlateGray\",\n        \"LightSlateGrey\",\n        \"LightSteelBlue\",\n        \"LightYellow\",\n        \"Lime\",\n        \"LimeGreen\",\n        \"Linen\",\n        \"Magenta\",\n        \"Maroon\",\n        \"MediumAquaMarine\",\n        \"MediumBlue\",\n        \"MediumOrchid\",\n        \"MediumPurple\",\n        \"MediumSeaGreen\",\n        \"MediumSlateBlue\",\n        \"MediumSpringGreen\",\n        \"MediumTurquoise\",\n        \"MediumVioletRed\",\n        \"MidnightBlue\",\n        \"MintCream\",\n        \"MistyRose\",\n        \"Moccasin\",\n        \"NavajoWhite\",\n        \"Navy\",\n        \"OldLace\",\n        \"Olive\",\n        \"OliveDrab\",\n        \"Orange\",\n        \"OrangeRed\",\n        \"Orchid\",\n        \"PaleGoldenRod\",\n        \"PaleGreen\",\n        \"PaleTurquoise\",\n        \"PaleVioletRed\",\n        \"PapayaWhip\",\n        \"PeachPuff\",\n        \"Peru\",\n        \"Pink\",\n        \"Plum\",\n        \"PowderBlue\",\n        \"Purple\",\n        \"Red\",\n        \"RosyBrown\",\n        \"RoyalBlue\",\n        \"SaddleBrown\",\n        \"Salmon\",\n        \"SandyBrown\",\n        \"SeaGreen\",\n        \"SeaShell\",\n        \"Sienna\",\n        \"Silver\",\n        \"SkyBlue\",\n        \"SlateBlue\",\n        \"SlateGray\",\n        \"SlateGrey\",\n        \"Snow\",\n        \"SpringGreen\",\n        \"SteelBlue\",\n        \"Tan\",\n        \"Teal\",\n        \"Thistle\",\n        \"Tomato\",\n        \"Turquoise\",\n        \"Violet\",\n        \"Wheat\",\n        \"White\",\n        \"WhiteSmoke\",\n        \"Yellow\",\n        \"YellowGreen\",\n    ]\n\n    // Match hex/rgb/rgba/hsl/hsla colors -\n    // courtesy of https://gist.github.com/olmokramer/82ccce673f86db7cda5e\n    // the first section matches a hex code which can be 3 or 6 digits long the\n    // next section matches rgb or hsl value with an a optionally\n    // NB - the regex was tweaked so it could match inside a string\n    private _colorCodeRegex = /#(?:[0-9a-f]{3}){1,2}|(rgb|hsl)a?\\((-?\\d+%?[,\\s]+){2,3}\\s*[\\d\\.]+%?\\)/gi\n    private _colorRegex: RegExp\n\n    private _fontSize: string\n    private _fontFamily: string\n\n    constructor(private _config: Oni.Configuration) {\n        this._fontSize = this._config.getValue(\"editor.fontSize\")\n        this._fontFamily = this._config.getValue(\"editor.fontFamily\")\n        this._config.onConfigurationChanged.subscribe(this._updateFontFamily)\n\n        this._constructRegex()\n    }\n\n    public get id() {\n        return \"color-highlight\"\n    }\n\n    public get friendlyName() {\n        return \"CSS color highlight layer\"\n    }\n\n    private _updateFontFamily = (configChanges: Partial<Oni.ConfigurationValues>) => {\n        const fontFamilyChanged = Object.keys(configChanges).includes(\"editor.fontFamily\")\n        if (fontFamilyChanged) {\n            this._fontFamily = configChanges[\"editor.fontFamily\"]\n        }\n    }\n\n    private _constructRegex() {\n        // Construct a regex checking for both color codes and all the different css colornames\n        const colorNames = this.CSS_COLOR_NAMES.map(name => `\\\\b${name}\\\\b`)\n        const colorNamesRegex = new RegExp(\"(\" + colorNames.join(\"|\") + \")\")\n        this._colorRegex = new RegExp(\n            colorNamesRegex.source + \"|\" + this._colorCodeRegex.source,\n            \"gi\",\n        )\n    }\n\n    private _getColorHighlights = (context: Oni.BufferLayerRenderContext) => {\n        return context.visibleLines.map((line, idx) => {\n            try {\n                const matches = line.match(this._colorRegex)\n                if (matches) {\n                    const colors = matches.filter(Boolean)\n                    if (colors.length) {\n                        const locations = colors.map(c => ({\n                            color: c,\n                            start: line.indexOf(c),\n                            end: line.indexOf(c) + c.length,\n                        }))\n                        const currentLine = context.topBufferLine + idx - 1\n                        return locations.map(location => {\n                            const startPosition = context.bufferToPixel({\n                                line: currentLine,\n                                character: location.start,\n                            })\n                            const endPosition = context.bufferToPixel({\n                                line: currentLine,\n                                character: location.end,\n                            })\n\n                            if (!startPosition || !endPosition) {\n                                return null\n                            }\n\n                            const width = endPosition.pixelX - startPosition.pixelX\n                            return (\n                                <Highlight\n                                    width={width}\n                                    left={startPosition.pixelX}\n                                    top={startPosition.pixelY}\n                                    height={context.fontPixelHeight}\n                                    fontSize={this._fontSize}\n                                    fontFamily={this._fontFamily}\n                                    color={location.color.toLowerCase()}\n                                >\n                                    {location.color}\n                                </Highlight>\n                            )\n                        })\n                    }\n                }\n            } catch (e) {\n                Log.warn(`Failed to create color highlights because ${e.message}`)\n                return null\n            }\n            return null\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/ImageBufferLayer.tsx",
    "content": "/**\n * ImageBufferLayer.tsx\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\n// import { inputManager, InputManager } from \"./../../Services/InputManager\"\n\nimport * as Oni from \"oni-api\"\n\nimport { withProps } from \"./../../UI/components/common\"\n// import { VimNavigator } from \"./../../UI/components/VimNavigator\"\n\nexport class ImageBufferLayer implements Oni.BufferLayer {\n    constructor(private _buffer: Oni.Buffer) {}\n    public get id(): string {\n        return \"oni.image\"\n    }\n\n    public get friendlyName(): string {\n        return \"Image\"\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return <ImageLayerView imagePath={this._buffer.filePath} key={this._buffer.filePath} />\n    }\n}\n\nexport interface IImageLayerViewProps {\n    imagePath: string\n}\n\nexport interface IImageLayerViewState {\n    width: number\n    height: number\n}\n\nconst ImageContainer = withProps<{}>(styled.div)`\n    background-color: ${props => props.theme[\"editor.background\"]};\n    color: ${props => props.theme[\"editor.foreground\"]};\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    flex-direction: column;\n    opacity: 0.95;\n\n    & img {\n        max-width: 90%;\n        max-height: 90%;\n\n        padding-bottom: 2em;\n    }\n`\n\nexport class ImageLayerView extends React.PureComponent<\n    IImageLayerViewProps,\n    IImageLayerViewState\n> {\n    constructor(props: IImageLayerViewProps) {\n        super(props)\n\n        this.state = {\n            width: -1,\n            height: -1,\n        }\n    }\n    public componentDidMount(): void {\n        const image = new Image()\n        image.onload = () => {\n            this.setState({\n                width: image.width,\n                height: image.height,\n            })\n        }\n        image.src = this.props.imagePath\n    }\n\n    public render(): JSX.Element {\n        const dimensions = this.state ? `${this.state.width}x${this.state.height}` : \"\"\n\n        return (\n            <ImageContainer>\n                <img src={this.props.imagePath} />\n                <div>{this.props.imagePath}</div>\n                <div>{dimensions}</div>\n            </ImageContainer>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/IndentGuideBufferLayer.tsx",
    "content": "import * as React from \"react\"\n\nimport * as detectIndent from \"detect-indent\"\nimport * as flatten from \"lodash/flatten\"\nimport * as last from \"lodash/last\"\nimport * as memoize from \"lodash/memoize\"\nimport * as Oni from \"oni-api\"\n\nimport { IBuffer } from \"../BufferManager\"\nimport styled, { pixel, withProps } from \"./../../UI/components/common\"\n\ninterface IWrappedLine {\n    start: number\n    end: number\n    line: string\n}\n\ninterface IProps {\n    height: number\n    left: number\n    top: number\n    color?: string\n}\n\ninterface ConfigOptions {\n    skipFirst: boolean\n    color?: string\n}\n\ninterface LinePropsWithLevels extends IndentLinesProps {\n    levelOfIndentation: number\n}\n\ninterface IndentLinesProps {\n    top: number\n    left: number\n    height: number\n    line: string\n    indentBy: number\n    indentSize: number\n    characterWidth: number\n}\n\nconst Container = styled.div``\n\nconst IndentLine = withProps<IProps>(styled.span).attrs({\n    style: ({ height, left, top }: IProps) => ({\n        height: pixel(height),\n        left: pixel(left),\n        top: pixel(top),\n    }),\n})`\n    border-left: 1px solid ${p => p.color || \"rgba(100, 100, 100, 0.4)\"};\n    position: absolute;\n`\n\ninterface IndentLayerArgs {\n    buffer: IBuffer\n    configuration: Oni.Configuration\n}\n\nclass IndentGuideBufferLayer implements Oni.BufferLayer {\n    public render = memoize((bufferLayerContext: Oni.BufferLayerRenderContext) => {\n        return <Container id={this.id}>{this._renderIndentLines(bufferLayerContext)}</Container>\n    })\n\n    private _buffer: IBuffer\n    private _userSpacing: number\n    private _configuration: Oni.Configuration\n\n    constructor({ buffer, configuration }: IndentLayerArgs) {\n        this._buffer = buffer\n        this._configuration = configuration\n        this._userSpacing = this._buffer.shiftwidth || this._buffer.tabstop\n    }\n    get id() {\n        return \"indent-guides\"\n    }\n\n    get friendlyName() {\n        return \"Indent Guide Lines\"\n    }\n\n    private _getIndentLines = (guidePositions: IndentLinesProps[], options: ConfigOptions) => {\n        return flatten(\n            guidePositions.map((props, idx) => {\n                const indents: JSX.Element[] = []\n                // Create a line per indentation\n                for (\n                    let levelOfIndentation = 0;\n                    levelOfIndentation < props.indentBy;\n                    levelOfIndentation++\n                ) {\n                    const lineProps = { ...props, levelOfIndentation }\n                    const adjustedLeft = this._calculateLeftPosition(lineProps)\n                    const shouldSkip = this._determineIfShouldSkip(lineProps, options)\n                    const key = `${props.line.trim()}-${idx}-${levelOfIndentation}`\n                    indents.push(\n                        !shouldSkip && (\n                            <IndentLine\n                                key={key}\n                                top={props.top}\n                                left={adjustedLeft}\n                                color={options.color}\n                                height={props.height}\n                                data-id=\"indent-line\"\n                            />\n                        ),\n                    )\n                }\n                return indents\n            }),\n        )\n    }\n\n    private _determineIfShouldSkip(props: LinePropsWithLevels, options: ConfigOptions) {\n        const skipFirstIndentLine =\n            options.skipFirst && props.levelOfIndentation === props.indentBy - 1\n\n        return skipFirstIndentLine\n    }\n\n    /**\n     * Remove one indent from left positioning and move lines slightly inwards -\n     * by a third of a character for a better visual appearance\n     */\n    private _calculateLeftPosition(props: LinePropsWithLevels) {\n        const adjustedLeft =\n            props.left -\n            props.indentSize -\n            props.levelOfIndentation * props.indentSize +\n            props.characterWidth / 3\n\n        return adjustedLeft\n    }\n\n    private _getWrappedLines(context: Oni.BufferLayerRenderContext): IWrappedLine[] {\n        const { lines } = context.visibleLines.reduce(\n            (acc, line, index) => {\n                const currentLine = context.topBufferLine + index\n                const bufferInfo = context.bufferToScreen({ line: currentLine, character: 0 })\n\n                if (bufferInfo && bufferInfo.screenY) {\n                    const { screenY: screenLine } = bufferInfo\n                    if (acc.expectedLine !== screenLine) {\n                        acc.lines.push({\n                            start: acc.expectedLine,\n                            end: screenLine,\n                            line,\n                        })\n                        acc.expectedLine = screenLine + 1\n                    } else {\n                        acc.expectedLine += 1\n                    }\n                }\n                return acc\n            },\n            { lines: [], expectedLine: 1 },\n        )\n        return lines\n    }\n\n    private _regulariseIndentation(indentation: detectIndent.IndentInfo) {\n        const isOddBy = indentation.amount % this._userSpacing\n        const amountToIndent = isOddBy ? indentation.amount - isOddBy : indentation.amount\n        return amountToIndent\n    }\n\n    /**\n     * Calculates the position of each indent guide element using shiftwidth or tabstop if no\n     * shift width available\n     * @name _renderIndentLines\n     * @function\n     * @param {Oni.BufferLayerRenderContext} bufferLayerContext The buffer layer context\n     * @returns {JSX.Element[]} An array of react elements\n     */\n    private _renderIndentLines = (bufferLayerContext: Oni.BufferLayerRenderContext) => {\n        // TODO: If the beginning of the visible lines is wrapping no lines are drawn\n        const wrappedScreenLines = this._getWrappedLines(bufferLayerContext)\n\n        const options = {\n            color: this._configuration.getValue<string>(\"experimental.indentLines.color\"),\n            skipFirst: this._configuration.getValue<boolean>(\"experimental.indentLines.skipFirst\"),\n        }\n\n        const { visibleLines, fontPixelHeight, fontPixelWidth, topBufferLine } = bufferLayerContext\n        const indentSize = this._userSpacing * fontPixelWidth\n\n        const { allIndentations } = visibleLines.reduce(\n            (acc, line, currenLineNumber) => {\n                const rawIndentation = detectIndent(line)\n\n                const regularisedIndent = this._regulariseIndentation(rawIndentation)\n\n                const previous = last(acc.allIndentations)\n                const height = Math.ceil(fontPixelHeight)\n\n                // start position helps determine the initial indent offset\n                const startPosition = bufferLayerContext.bufferToScreen({\n                    line: topBufferLine,\n                    character: regularisedIndent,\n                })\n\n                const wrappedLine = wrappedScreenLines.find(wrapped => wrapped.line === line)\n                const levelsOfWrapping = wrappedLine ? wrappedLine.end - wrappedLine.start : 1\n                const adjustedHeight = height * levelsOfWrapping\n\n                if (!startPosition) {\n                    return acc\n                }\n\n                const { pixelX: left, pixelY: top } = bufferLayerContext.screenToPixel({\n                    screenX: startPosition.screenX,\n                    screenY: currenLineNumber,\n                })\n\n                const adjustedTop = top + acc.wrappedHeightAdjustment\n\n                // Only adjust height for Subsequent lines!\n                if (wrappedLine) {\n                    acc.wrappedHeightAdjustment += adjustedHeight\n                }\n\n                if (!line && previous) {\n                    acc.allIndentations.push({\n                        ...previous,\n                        line,\n                        top: adjustedTop,\n                    })\n                    return acc\n                }\n\n                const indent = {\n                    left,\n                    line,\n                    indentSize,\n                    top: adjustedTop,\n                    height: adjustedHeight,\n                    characterWidth: fontPixelWidth,\n                    indentBy: regularisedIndent / this._userSpacing,\n                }\n\n                acc.allIndentations.push(indent)\n\n                return acc\n            },\n            { allIndentations: [], wrappedHeightAdjustment: 0 },\n        )\n\n        return this._getIndentLines(allIndentations, options)\n    }\n}\n\nexport default IndentGuideBufferLayer\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/OniEditor.tsx",
    "content": "/**\n * OniEditor.ts\n *\n * Editor implementation for Oni\n *\n * Extends the capabilities of the NeovimEditor\n */\n\nimport * as path from \"path\"\nimport * as React from \"react\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { IEvent } from \"oni-types\"\n\n// import { remote } from \"electron\"\n\nimport * as App from \"./../../App\"\nimport * as Utility from \"./../../Utility\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { IColors } from \"./../../Services/Colors\"\nimport { commandManager } from \"./../../Services/CommandManager\"\nimport { CompletionProviders } from \"./../../Services/Completion\"\nimport { Configuration } from \"./../../Services/Configuration\"\nimport { IDiagnosticsDataSource } from \"./../../Services/Diagnostics\"\n\nimport { editorManager } from \"./../../Services/EditorManager\"\nimport { LanguageManager } from \"./../../Services/Language\"\n\nimport { MenuManager } from \"./../../Services/Menu\"\nimport { OverlayManager } from \"./../../Services/Overlay\"\n\nimport { SnippetManager } from \"./../../Services/Snippets\"\nimport { ISyntaxHighlighter } from \"./../../Services/SyntaxHighlighting\"\n\nimport { ThemeManager } from \"./../../Services/Themes\"\nimport { TokenColors } from \"./../../Services/TokenColors\"\nimport { Workspace } from \"./../../Services/Workspace\"\n\nimport { BufferScrollBarContainer } from \"./containers/BufferScrollBarContainer\"\nimport { DefinitionContainer } from \"./containers/DefinitionContainer\"\nimport { ErrorsContainer } from \"./containers/ErrorsContainer\"\n\nimport { NeovimEditor } from \"./../NeovimEditor\"\n\nimport { SplitDirection, windowManager } from \"./../../Services/WindowManager\"\n\nimport { ISession } from \"../../Services/Sessions\"\nimport { IBuffer } from \"../BufferManager\"\nimport { OniWithActiveSection, WelcomeBufferLayer } from \"../NeovimEditor/WelcomeBufferLayer\"\nimport ColorHighlightLayer from \"./ColorHighlightLayer\"\nimport { ImageBufferLayer } from \"./ImageBufferLayer\"\nimport IndentLineBufferLayer from \"./IndentGuideBufferLayer\"\n\n// Helper method to wrap a react component into a layer\nconst wrapReactComponentWithLayer = (id: string, component: JSX.Element): Oni.BufferLayer => {\n    return {\n        id,\n        render: (context: Oni.BufferLayerRenderContext) => (context.isActive ? component : null),\n    }\n}\n\nexport class OniEditor extends Utility.Disposable implements Oni.Editor {\n    private _neovimEditor: NeovimEditor\n\n    public get mode(): string {\n        return this._neovimEditor.mode\n    }\n\n    public get onCursorMoved(): IEvent<Oni.Cursor> {\n        return this._neovimEditor.onCursorMoved\n    }\n\n    public get onModeChanged(): IEvent<Oni.Vim.Mode> {\n        return this._neovimEditor.onModeChanged\n    }\n\n    public get onBufferEnter(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._neovimEditor.onBufferEnter\n    }\n\n    public get onBufferLeave(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._neovimEditor.onBufferLeave\n    }\n\n    public get onBufferChanged(): IEvent<Oni.EditorBufferChangedEventArgs> {\n        return this._neovimEditor.onBufferChanged\n    }\n\n    public get onBufferSaved(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._neovimEditor.onBufferSaved\n    }\n\n    public get onBufferScrolled(): IEvent<Oni.EditorBufferScrolledEventArgs> {\n        return this._neovimEditor.onBufferScrolled\n    }\n\n    public get /* override */ activeBuffer(): Oni.Buffer {\n        return this._neovimEditor.activeBuffer\n    }\n\n    public get onQuit(): IEvent<void> {\n        return this._neovimEditor.onNeovimQuit\n    }\n\n    // Capabilities\n    public get neovim(): Oni.NeovimEditorCapability {\n        return this._neovimEditor.neovim\n    }\n\n    public get syntaxHighlighter(): ISyntaxHighlighter {\n        return this._neovimEditor.syntaxHighlighter\n    }\n\n    constructor(\n        private _colors: IColors,\n        private _completionProviders: CompletionProviders,\n        private _configuration: Configuration,\n        private _diagnostics: IDiagnosticsDataSource,\n        private _languageManager: LanguageManager,\n        private _menuManager: MenuManager,\n        private _overlayManager: OverlayManager,\n        private _pluginManager: PluginManager,\n        private _snippetManager: SnippetManager,\n        private _themeManager: ThemeManager,\n        private _tokenColors: TokenColors,\n        private _workspace: Workspace,\n    ) {\n        super()\n\n        this._neovimEditor = new NeovimEditor(\n            this._colors,\n            this._completionProviders,\n            this._configuration,\n            this._diagnostics,\n            this._languageManager,\n            this._menuManager,\n            this._overlayManager,\n            this._pluginManager,\n            this._snippetManager,\n            this._themeManager,\n            this._tokenColors,\n            this._workspace,\n        )\n\n        editorManager.registerEditor(this)\n\n        this.trackDisposable(\n            this._neovimEditor.onNeovimQuit.subscribe(() => {\n                const handle = windowManager.getSplitHandle(this)\n                handle.close()\n                editorManager.unregisterEditor(this)\n\n                this.dispose()\n            }),\n        )\n\n        this.trackDisposable(\n            App.registerQuitHook(async () => {\n                if (!this.isDisposed) {\n                    this.quit()\n                }\n            }),\n        )\n\n        this._neovimEditor.bufferLayers.addBufferLayer(\"*\", buf =>\n            wrapReactComponentWithLayer(\"oni.layer.scrollbar\", <BufferScrollBarContainer />),\n        )\n        this._neovimEditor.bufferLayers.addBufferLayer(\"*\", buf =>\n            wrapReactComponentWithLayer(\"oni.layer.definition\", <DefinitionContainer />),\n        )\n        this._neovimEditor.bufferLayers.addBufferLayer(\"*\", buf =>\n            wrapReactComponentWithLayer(\"oni.layer.errors\", <ErrorsContainer />),\n        )\n\n        const imageExtensions = this._configuration.getValue(\"editor.imageLayerExtensions\")\n        const bannedIndentExtensions = this._configuration.getValue(\n            \"experimental.indentLines.bannedFiletypes\",\n        )\n\n        this._neovimEditor.bufferLayers.addBufferLayer(\n            buf => imageExtensions.includes(path.extname(buf.filePath)),\n            buf => new ImageBufferLayer(buf),\n        )\n\n        if (this._configuration.getValue(\"experimental.indentLines.enabled\")) {\n            this._neovimEditor.bufferLayers.addBufferLayer(\n                buf => {\n                    const extension = path.extname(buf.filePath)\n                    return extension && !bannedIndentExtensions.includes(extension)\n                },\n                buffer =>\n                    new IndentLineBufferLayer({\n                        buffer: buffer as IBuffer,\n                        configuration: this._configuration,\n                    }),\n            )\n        }\n        if (this._configuration.getValue(\"experimental.colorHighlight.enabled\")) {\n            this._neovimEditor.bufferLayers.addBufferLayer(\n                buf =>\n                    this._configuration\n                        .getValue(\"experimental.colorHighlight.filetypes\")\n                        .includes(path.extname(buf.filePath)),\n                _buf => new ColorHighlightLayer(this._configuration),\n            )\n        }\n\n        this._neovimEditor.onShowWelcomeScreen.subscribe(this.openWelcomeScreen)\n    }\n\n    public dispose(): void {\n        super.dispose()\n\n        if (this._neovimEditor) {\n            this._neovimEditor.dispose()\n            this._neovimEditor = null\n        }\n    }\n\n    public enter(): void {\n        Log.info(\"[OniEditor::enter]\")\n        editorManager.setActiveEditor(this)\n\n        this._neovimEditor.enter()\n\n        commandManager.registerCommand({\n            name: \"Oni: Show Welcome\",\n            detail: \"Open the welcome screen\",\n            command: \"oni.welcome.open\",\n            execute: this.openWelcomeScreen,\n            enabled: () => this._configuration.getValue(\"experimental.welcome.enabled\"),\n        })\n\n        commandManager.registerCommand({\n            command: \"editor.split.horizontal\",\n            execute: () => this._split(\"horizontal\"),\n            enabled: () => editorManager.activeEditor === this,\n            name: null,\n            detail: null,\n        })\n\n        commandManager.registerCommand({\n            command: \"editor.split.vertical\",\n            execute: () => this._split(\"vertical\"),\n            enabled: () => editorManager.activeEditor === this,\n            name: null,\n            detail: null,\n        })\n    }\n\n    public leave(): void {\n        Log.info(\"[OniEditor::leave]\")\n        this._neovimEditor.leave()\n    }\n\n    public openWelcomeScreen = async () => {\n        const oni = this._pluginManager.getApi()\n        const welcomeBuffer = await this._neovimEditor.createWelcomeBuffer()\n        const welcomeLayer = new WelcomeBufferLayer(oni as OniWithActiveSection)\n        welcomeBuffer.addLayer(welcomeLayer)\n    }\n\n    public async openFile(\n        file: string,\n        openOptions: Oni.FileOpenOptions = Oni.DefaultFileOpenOptions,\n    ): Promise<Oni.Buffer> {\n        const openMode = openOptions.openMode\n        if (this._configuration.getValue(\"editor.split.mode\") === \"oni\") {\n            if (\n                openMode === Oni.FileOpenMode.HorizontalSplit ||\n                openMode === Oni.FileOpenMode.VerticalSplit\n            ) {\n                const splitDirection =\n                    openMode === Oni.FileOpenMode.HorizontalSplit ? \"horizontal\" : \"vertical\"\n                const newEditor = await this._split(splitDirection)\n                return newEditor.openFile(file, { openMode: Oni.FileOpenMode.Edit })\n            }\n        }\n\n        return this._neovimEditor.openFile(file, openOptions)\n    }\n\n    public async newFile(filePath: string): Promise<Oni.Buffer> {\n        return this._neovimEditor.newFile(filePath)\n    }\n\n    public async clearSelection(): Promise<void> {\n        return this._neovimEditor.clearSelection()\n    }\n\n    public async setSelection(range: types.Range): Promise<void> {\n        return this._neovimEditor.setSelection(range)\n    }\n\n    public async setTextOptions(textOptions: Oni.EditorTextOptions): Promise<void> {\n        return this._neovimEditor.setTextOptions(textOptions)\n    }\n\n    public async blockInput(\n        inputFunction: (input: Oni.InputCallbackFunction) => Promise<void>,\n    ): Promise<void> {\n        return this._neovimEditor.blockInput(inputFunction)\n    }\n\n    public executeCommand(command: string): void {\n        this._neovimEditor.executeCommand(command)\n    }\n\n    public restoreSession(sessionDetails: ISession) {\n        return this._neovimEditor.restoreSession(sessionDetails)\n    }\n\n    public getCurrentSession() {\n        return this._neovimEditor.getCurrentSession()\n    }\n\n    public persistSession(sessionDetails: ISession) {\n        return this._neovimEditor.persistSession(sessionDetails)\n    }\n\n    public getBuffers(): Array<Oni.Buffer | Oni.InactiveBuffer> {\n        return this._neovimEditor.getBuffers()\n    }\n\n    public async bufferDelete(bufferId: string = this.activeBuffer.id): Promise<void> {\n        this._neovimEditor.bufferDelete(bufferId)\n    }\n\n    public async init(filesToOpen: string[]): Promise<void> {\n        Log.info(\"[OniEditor::init] Called with filesToOpen: \" + filesToOpen)\n\n        return this._neovimEditor.init(filesToOpen)\n    }\n\n    public async input(key: string): Promise<void> {\n        return this._neovimEditor.input(key)\n    }\n\n    public render(): JSX.Element {\n        return this._neovimEditor.render()\n    }\n\n    public async quit(): Promise<void> {\n        return this._neovimEditor.quit()\n    }\n\n    private async _split(direction: SplitDirection): Promise<OniEditor> {\n        if (this._configuration.getValue(\"editor.split.mode\") !== \"oni\") {\n            if (direction === \"horizontal\") {\n                await this._neovimEditor.neovim.command(\":sp\")\n            } else {\n                await this._neovimEditor.neovim.command(\":vsp\")\n            }\n\n            return this\n        }\n\n        const newEditor = new OniEditor(\n            this._colors,\n            this._completionProviders,\n            this._configuration,\n            this._diagnostics,\n            this._languageManager,\n            this._menuManager,\n            this._overlayManager,\n            this._pluginManager,\n            this._snippetManager,\n            this._themeManager,\n            this._tokenColors,\n            this._workspace,\n        )\n\n        windowManager.createSplit(direction, newEditor, this)\n        await newEditor.init([])\n        return newEditor\n    }\n}\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/containers/BufferScrollBarContainer.ts",
    "content": "import * as types from \"vscode-languageserver-types\"\n\nimport { connect } from \"react-redux\"\nimport { createSelector } from \"reselect\"\n\nimport { getColorFromSeverity } from \"./../../../Services/Diagnostics\"\nimport {\n    BufferScrollBar,\n    IBufferScrollBarProps,\n    IScrollBarMarker,\n} from \"./../../../UI/components/BufferScrollBar\"\n\nimport * as Selectors from \"./../../NeovimEditor/NeovimEditorSelectors\"\nimport * as State from \"./../../NeovimEditor/NeovimEditorStore\"\n\nexport const getCurrentLine = createSelector([Selectors.getActiveWindow], activeWindow => {\n    return activeWindow.line\n})\n\nconst NoScrollBar: IBufferScrollBarProps = {\n    windowId: null,\n    bufferSize: -1,\n    height: -1,\n    windowTopLine: -1,\n    windowBottomLine: -1,\n    markers: [],\n    visible: false,\n}\n\nexport const shouldIncludeCursorMarker = (state: State.IState) => {\n    return state.configuration[\"editor.scrollBar.cursorTick.visible\"]\n}\n\nexport const getMarkers = createSelector(\n    [getCurrentLine, Selectors.getErrorsForActiveFile, shouldIncludeCursorMarker],\n    (activeLine, fileErrors, includeCursor) => {\n        const errorMarkers = fileErrors.map((e: types.Diagnostic) => ({\n            line: e.range.start.line || 0,\n            height: 1,\n            color: getColorFromSeverity(e.severity),\n        }))\n\n        if (!includeCursor) {\n            return errorMarkers\n        } else {\n            const cursorMarker: IScrollBarMarker = {\n                line: activeLine - 1,\n                height: 1,\n                color: \"rgb(200, 200, 200)\",\n            }\n\n            return [...errorMarkers, cursorMarker]\n        }\n    },\n)\n\nconst mapStateToProps = (state: State.IState): IBufferScrollBarProps => {\n    const visible = state.configuration[\"editor.scrollBar.visible\"]\n\n    const activeWindow = Selectors.getActiveWindow(state)\n\n    if (!activeWindow) {\n        return NoScrollBar\n    }\n\n    const dimensions = Selectors.getActiveWindowPixelDimensions(state)\n\n    const file = activeWindow.file\n    const buffer = Selectors.getActiveBuffer(state)\n\n    if (file === null || !buffer) {\n        return NoScrollBar\n    }\n\n    const bufferSize = buffer.totalLines\n\n    const markers = getMarkers(state)\n\n    return {\n        windowId: activeWindow.windowId,\n        windowTopLine: activeWindow.topBufferLine,\n        windowBottomLine: activeWindow.bottomBufferLine,\n        bufferSize,\n        markers,\n        height: dimensions.height,\n        visible,\n    }\n}\n\nexport const BufferScrollBarContainer = connect(mapStateToProps)(BufferScrollBar)\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/containers/DefinitionContainer.ts",
    "content": "import { connect } from \"react-redux\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Definition, IDefinitionProps } from \"./../../../UI/components/Definition\"\n\nimport * as Selectors from \"./../../NeovimEditor/NeovimEditorSelectors\"\nimport * as State from \"./../../NeovimEditor/NeovimEditorStore\"\n\nconst emptyRange = types.Range.create(types.Position.create(-1, -1), types.Position.create(-1, -1))\n\nconst getActiveDefinition = (state: State.IState) => state.definition\n\nconst mapStateToProps = (state: State.IState): IDefinitionProps => {\n    const window = Selectors.getActiveWindow(state)\n\n    const noop = (): any => null\n\n    const activeDefinition = getActiveDefinition(state)\n\n    const range = activeDefinition ? activeDefinition.token.range : emptyRange\n\n    return {\n        color: state.colors[\"editor.foreground\"],\n        range,\n        fontWidthInPixels: state.fontPixelWidth,\n        fontHeightInPixels: state.fontPixelHeight,\n        bufferToScreen: window ? window.bufferToScreen : noop,\n        screenToPixel: window ? window.screenToPixel : noop,\n    }\n}\n\nexport const DefinitionContainer = connect(mapStateToProps)(Definition)\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/containers/ErrorsContainer.ts",
    "content": "import { connect } from \"react-redux\"\n\nimport { Errors, IErrorsProps } from \"./../../../UI/components/Error\"\n\nimport * as Selectors from \"./../../NeovimEditor/NeovimEditorSelectors\"\nimport * as State from \"./../../NeovimEditor/NeovimEditorStore\"\n\nconst mapStateToProps = (state: State.IState): IErrorsProps => {\n    const window = Selectors.getActiveWindow(state)\n    const errors = Selectors.getErrorsForActiveFile(state)\n\n    const noop = (): any => null\n\n    return {\n        errors,\n        fontWidthInPixels: state.fontPixelWidth,\n        fontHeightInPixels: state.fontPixelHeight,\n        bufferToScreen: window ? window.bufferToScreen : noop,\n        screenToPixel: window ? window.screenToPixel : noop,\n    }\n}\n\nexport const ErrorsContainer = connect(mapStateToProps)(Errors)\n"
  },
  {
    "path": "browser/src/Editor/OniEditor/index.ts",
    "content": "export * from \"./OniEditor\"\n"
  },
  {
    "path": "browser/src/Font.ts",
    "content": "export const FallbackFonts =\n    \"Consolas,Monaco,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace\"\n\nexport interface IFontMeasurement {\n    width: number\n    height: number\n}\n\nexport function measureFont(\n    fontFamily: string,\n    fontSize: string,\n    fontWeight: string,\n    characterToTest = \"H\",\n) {\n    const div = document.createElement(\"div\")\n\n    div.style.position = \"absolute\"\n    div.style.left = \"10px\"\n    div.style.top = \"10px\"\n    div.style.backgroundColor = \"red\"\n    div.style.left = \"-1000px\"\n    div.style.top = \"-1000px\"\n    div.textContent = characterToTest\n    div.style.fontFamily = `${fontFamily},${FallbackFonts}`\n    div.style.fontSize = fontSize\n    div.style.fontWeight = fontWeight\n\n    const isItalicAvailable = isStyleAvailable(fontFamily, \"italic\", fontSize)\n    const isBoldAvailable = isStyleAvailable(fontFamily, \"bold\", fontSize)\n\n    document.body.appendChild(div)\n\n    const rect = div.getBoundingClientRect()\n    const width = rect.width\n    const height = rect.height\n\n    document.body.removeChild(div)\n\n    return {\n        width,\n        height,\n        isItalicAvailable,\n        isBoldAvailable,\n    }\n}\n\nexport function addDefaultUnitIfNeeded(fontSize: string) {\n    const roundFont = `${Math.round(parseFloat(fontSize))}px`\n    return roundFont\n}\n\nexport function isStyleAvailable(fontName: string, style: string, fontSize = \"12px\") {\n    const text = \"abcdefghijklmnopqrstuvwxyz0123456789\"\n    let canvas = document.createElement(\"canvas\")\n    const context = canvas.getContext(\"2d\")\n    context.font = `${fontSize} ${fontName}`\n    const baselineSize = context.measureText(text).width\n    context.font = `${style} ${fontSize} ${fontName}`\n    const newSize = context.measureText(text).width\n    canvas = null\n    return newSize === baselineSize\n}\n"
  },
  {
    "path": "browser/src/Grid.ts",
    "content": "export class Grid<T> {\n    private _cells: any = {}\n\n    private _width: number = 0\n    private _height: number = 0\n\n    public get width(): number {\n        return this._width\n    }\n\n    public get height(): number {\n        return this._height\n    }\n\n    public getCell(x: number, y: number): null | T {\n        const row = this._cells[y]\n\n        if (!row) {\n            return null\n        }\n\n        const col = row[x]\n\n        if (typeof col === \"undefined\") {\n            return null\n        }\n\n        return col\n    }\n\n    public setCell(x: number, y: number, val: T | null) {\n        let row = this._cells[y]\n        row = row || {}\n        row[x] = val\n        this._cells[y] = row\n\n        if (x >= this._width) {\n            this._width = x + 1\n        }\n\n        if (y >= this._height) {\n            this._height = y + 1\n        }\n    }\n\n    public clear(): void {\n        this._cells = {}\n        this._width = 0\n        this._height = 0\n    }\n\n    public shiftRows(rowsToShift: number): void {\n        // var val = typeof defaultVal === \"undefined\" ? null : defaultVal\n\n        let dir: any\n        let start: any\n\n        if (rowsToShift >= 0) {\n            dir = 1\n            start = 0\n        } else {\n            dir = -1\n            start = this._height - 1\n        }\n\n        let current = start\n\n        while (current >= 0 && current < this._height) {\n            const srcRow = current + rowsToShift\n\n            for (let x = 0; x < this._width; x++) {\n                const oldCell = this.getCell(x, srcRow)\n                this.setCell(x, current, oldCell as any)\n            }\n\n            current += dir\n        }\n    }\n\n    public setRegionFromGrid(grid: Grid<T>, xPosition: number, yPosition: number): void {\n        for (let x = 0; x < grid.width; x++) {\n            for (let y = 0; y < grid.height; y++) {\n                const sourceCell = grid.getCell(x, y)\n                this.setCell(xPosition + x, yPosition + y, sourceCell)\n            }\n        }\n    }\n\n    public setRegion(\n        startX: number,\n        startY: number,\n        width: number,\n        height: number,\n        val?: T | null,\n    ): void {\n        const valToSet = typeof val === \"undefined\" ? null : val\n        for (let x = startX; x < startX + width; x++) {\n            for (let y = startY; y < startY + height; y++) {\n                this.setCell(x, y, valToSet)\n            }\n        }\n    }\n\n    public cloneRegion(x: number, y: number, width: number, height: number): Grid<T> {\n        const outputGrid = new Grid<T>()\n        for (let cloneX = 0; cloneX < width; cloneX++) {\n            for (let cloneY = 0; cloneY < height; cloneY++) {\n                const sourceCell = this.getCell(cloneX + x, cloneY + y)\n                outputGrid.setCell(cloneX, cloneY, sourceCell)\n            }\n        }\n\n        return outputGrid\n    }\n}\n"
  },
  {
    "path": "browser/src/Input/KeyBindings.ts",
    "content": "/**\n * KeyBindings.ts\n *\n * Default, out-of-the-box keybindings for Oni\n */\n\nimport * as Oni from \"oni-api\"\n\nimport * as Platform from \"./../Platform\"\nimport { Configuration } from \"./../Services/Configuration\"\n\ninterface ISidebar {\n    sidebar: {\n        activeEntryId: string\n        isFocused: boolean\n    }\n}\n\nexport const applyDefaultKeyBindings = (oni: Oni.Plugin.Api, config: Configuration): void => {\n    const { editors, input, menu } = oni\n\n    input.unbindAll()\n\n    const isVisualMode = () => editors.activeEditor.mode === \"visual\"\n    const isNormalMode = () => editors.activeEditor.mode === \"normal\"\n    const isNotInsertMode = () => editors.activeEditor.mode !== \"insert\"\n    const isInsertOrCommandMode = () =>\n        editors.activeEditor.mode === \"insert\" || editors.activeEditor.mode === \"cmdline_normal\"\n\n    const oniWithSidebar = oni as Oni.Plugin.Api & ISidebar\n    const isSidebarPaneOpen = (paneId: string) =>\n        oniWithSidebar.sidebar.activeEntryId === paneId &&\n        oniWithSidebar.sidebar.isFocused &&\n        !isInsertOrCommandMode() &&\n        !isMenuOpen()\n\n    const isExplorerActive = () => isSidebarPaneOpen(\"oni.sidebar.explorer\")\n    const areSessionsActive = () => isSidebarPaneOpen(\"oni.sidebar.sessions\")\n    const isVCSActive = () => isSidebarPaneOpen(\"oni.sidebar.vcs\")\n\n    const isMenuOpen = () => menu.isMenuOpen()\n\n    if (Platform.isMac()) {\n        input.bind(\"<m-q>\", \"oni.quit\")\n        input.bind(\"<m-p>\", \"quickOpen.show\", () => isNormalMode() && !isMenuOpen())\n        input.bind(\"<m-s-p>\", \"commands.show\", isNormalMode)\n        input.bind(\"<m-enter>\", \"language.codeAction.expand\")\n        input.bind(\"<m-t>\", \"language.symbols.workspace\", () => !menu.isMenuOpen())\n        input.bind(\"<s-m-t>\", \"language.symbols.document\")\n        input.bind(\"<m-m>\", \"oni.editor.minimize\")\n        input.bind(\"<m-h>\", \"oni.editor.hide\")\n        input.bind(\"<c-tab>\", \"buffer.toggle\")\n        input.bind(\"<m-s-f>\", \"search.searchAllFiles\")\n        input.bind(\"<m-s-e>\", \"explorer.toggle\")\n        input.bind(\"<m-s-_>\", \"sidebar.decreaseWidth\")\n        input.bind(\"<m-s-+>\", \"sidebar.increaseWidth\")\n        input.bind(\"<m-,>\", \"oni.config.openConfigJs\")\n\n        if (config.getValue(\"editor.clipboard.enabled\")) {\n            input.bind(\"<m-c>\", \"editor.clipboard.yank\", isVisualMode)\n            input.bind(\"<m-v>\", \"editor.clipboard.paste\", isInsertOrCommandMode)\n        }\n\n        // Browser\n        input.bind(\"<m-left>\", \"browser.goBack\")\n        input.bind(\"<m-right>\", \"browser.goForward\")\n        input.bind(\"<m-r>\", \"browser.reload\")\n    } else {\n        input.bind(\"<a-f4>\", \"oni.quit\")\n        input.bind(\"<s-c-_>\", \"sidebar.decreaseWidth\")\n        input.bind(\"<s-c-+>\", \"sidebar.increaseWidth\")\n        input.bind(\"<c-p>\", \"quickOpen.show\", () => isNormalMode() && !isMenuOpen())\n        input.bind(\"<s-c-p>\", \"commands.show\", isNormalMode)\n        input.bind(\"<a-enter>\", \"language.codeAction.expand\")\n        input.bind(\"<c-t>\", \"language.symbols.workspace\", () => !menu.isMenuOpen())\n        input.bind(\"<s-c-t>\", \"language.symbols.document\")\n        input.bind(\"<c-tab>\", \"buffer.toggle\")\n        input.bind(\"<s-c-f>\", \"search.searchAllFiles\")\n        input.bind(\"<s-c-e>\", \"explorer.toggle\")\n        input.bind(\"<c-,>\", \"oni.config.openConfigJs\")\n\n        if (config.getValue(\"editor.clipboard.enabled\")) {\n            input.bind(\"<c-c>\", \"editor.clipboard.yank\", isVisualMode)\n            input.bind(\"<c-v>\", \"editor.clipboard.paste\", isInsertOrCommandMode)\n        }\n\n        // Browser\n        input.bind(\"<a-left>\", \"browser.goBack\")\n        input.bind(\"<a-right>\", \"browser.goForward\")\n        input.bind(\"<f5>\", \"browser.reload\")\n    }\n\n    input.bind(\"<f2>\", \"editor.rename\", () => isNormalMode())\n\n    input.bind(\"<f3>\", \"language.format\")\n    input.bind([\"<f12>\"], \"language.gotoDefinition\", () => isNormalMode() && !menu.isMenuOpen())\n    input.bind(\n        [\"<c-enter>\", \"<c-f12>\"],\n        \"language.gotoDefinition.openVertical\",\n        () => isNormalMode() && !menu.isMenuOpen(),\n    )\n    input.bind(\n        [\"<s-enter>\", \"<s-f12>\"],\n        \"language.gotoDefinition.openHorizontal\",\n        () => isNormalMode() && !menu.isMenuOpen(),\n    )\n    input.bind(\"<S-C-P>\", \"commands.show\", isNormalMode)\n    input.bind(\"<C-pageup>\", \"oni.process.cyclePrevious\")\n    input.bind(\"<C-pagedown>\", \"oni.process.cycleNext\")\n\n    // QuickOpen\n    input.bind(\"<C-/>\", \"quickOpen.showBufferLines\", isNormalMode)\n    input.bind([\"<C-v>\"], \"quickOpen.openFileVertical\")\n    input.bind([\"<C-s>\"], \"quickOpen.openFileHorizontal\")\n    input.bind(\"<C-t>\", \"quickOpen.openFileNewTab\")\n    input.bind([\"<C-enter>\"], \"quickOpen.openFileAlternative\")\n\n    // Snippets\n    input.bind(\"<tab>\", \"snippet.nextPlaceholder\")\n    input.bind(\"<s-tab>\", \"snippet.previousPlaceholder\")\n    input.bind(\"<esc>\", \"snippet.cancel\")\n\n    // Completion\n    input.bind([\"<enter>\"], \"contextMenu.select\")\n    input.bind([\"<down>\", \"<C-n>\"], \"contextMenu.next\")\n    input.bind([\"<up>\", \"<C-p>\"], \"contextMenu.previous\")\n    input.bind(\n        [\"<esc>\"],\n        \"contextMenu.close\",\n        isNotInsertMode /* In insert mode, the mode change will close the popupmenu anyway */,\n    )\n\n    // Menu\n    input.bind([\"<down>\", \"<C-n>\"], \"menu.next\")\n    input.bind([\"<up>\", \"<C-p>\"], \"menu.previous\")\n    input.bind([\"<esc>\", \"<C-[>\", \"<C-C>\"], \"menu.close\")\n    input.bind(\"<enter>\", \"menu.select\")\n    input.bind([\"<enter>\", \"<space>\"], \"select\")\n\n    // TODO: Scope 's' to just the local window\n    input.bind(\"<c-g>\", \"sneak.show\", () => isNormalMode() && !menu.isMenuOpen())\n    input.bind([\"<esc>\", \"<c-c>\"], \"sneak.hide\")\n\n    input.bind(\"<s-c-b>\", \"sidebar.toggle\", isNormalMode)\n\n    // Explorer\n    input.bind(\"d\", \"explorer.delete.persist\", isExplorerActive)\n    input.bind(\"<c-delete>\", \"explorer.delete.persist\", isExplorerActive)\n    input.bind(\"<c-s-d>\", \"explorer.delete\", isExplorerActive)\n    input.bind(\"<delete>\", \"explorer.delete\", isExplorerActive)\n    input.bind(\"y\", \"explorer.yank\", isExplorerActive)\n    input.bind(\"p\", \"explorer.paste\", isExplorerActive)\n    input.bind(\"u\", \"explorer.undo\", isExplorerActive)\n    input.bind(\"h\", \"explorer.collapse.directory\", isExplorerActive)\n    input.bind(\"l\", \"explorer.expand.directory\", isExplorerActive)\n    input.bind(\"r\", \"explorer.rename\", isExplorerActive)\n    input.bind(\"<c-e>\", \"explorer.create.file\", isExplorerActive)\n    input.bind(\"<c-f>\", \"explorer.create.folder\", isExplorerActive)\n    input.bind(\"<c-r>\", \"explorer.refresh\", isExplorerActive)\n\n    // Browser\n    input.bind(\"k\", \"browser.scrollUp\")\n    input.bind(\"j\", \"browser.scrollDown\")\n    input.bind(\"h\", \"browser.scrollLeft\")\n    input.bind(\"l\", \"browser.scrollRight\")\n\n    // VCS\n    input.bind(\"e\", \"vcs.openFile\", isVCSActive)\n    input.bind(\"u\", \"vcs.unstage\", isVCSActive)\n    input.bind(\"<c-r>\", \"vcs.refresh\", isVCSActive)\n    input.bind(\"?\", \"vcs.showHelp\", isVCSActive)\n\n    // Sessions\n    input.bind(\"<c-d>\", \"oni.sessions.delete\", areSessionsActive)\n}\n"
  },
  {
    "path": "browser/src/Input/KeyParser.ts",
    "content": "/**\n * KeyParser.ts\n *\n * Simple parsing logic to take vim key bindings / chords,\n * and return a normalized object.\n */\n\nexport interface IKey {\n    character: string\n    shift: boolean\n    alt: boolean\n    control: boolean\n    meta: boolean\n}\n\nexport interface IKeyChord {\n    chord: IKey[]\n}\n\nexport const parseKeysFromVimString = (keys: string): IKeyChord => {\n    const chord: IKey[] = []\n\n    let idx = 0\n\n    while (idx < keys.length) {\n        if (keys[idx] !== \"<\") {\n            chord.push(parseKey(keys[idx]))\n        } else {\n            const endIndex = getNextCharacter(keys, idx + 1)\n            // Malformed if there isn't a corresponding '>'\n            if (endIndex === -1) {\n                return { chord }\n            }\n\n            const keyContents = keys.substring(idx + 1, endIndex)\n            chord.push(parseKey(keyContents))\n            idx = endIndex + 1\n        }\n\n        idx++\n    }\n\n    return {\n        chord,\n    }\n}\n\nconst getNextCharacter = (str: string, startIndex: number): number => {\n    let i = startIndex\n    while (i < str.length) {\n        if (str[i] === \">\") {\n            return i\n        }\n        i++\n    }\n\n    return -1\n}\n\nexport const parseKey = (key: string): IKey => {\n    if (key.indexOf(\"-\") === -1) {\n        return {\n            character: key,\n            shift: false,\n            alt: false,\n            control: false,\n            meta: false,\n        }\n    }\n\n    const hasControl = key.indexOf(\"c-\") >= 0 || key.indexOf(\"C-\") >= 0\n    const hasShift = key.indexOf(\"s-\") >= 0 || key.indexOf(\"S-\") >= 0\n    const hasAlt = key.indexOf(\"a-\") >= 0 || key.indexOf(\"A-\") >= 0\n    const hasMeta = key.indexOf(\"m-\") >= 0 || key.indexOf(\"M-\") >= 0\n\n    const lastIndexoFHyphen = key.lastIndexOf(\"-\")\n    const finalKey = key.substring(lastIndexoFHyphen + 1, key.length)\n\n    return {\n        character: finalKey,\n        shift: hasShift,\n        alt: hasAlt,\n        control: hasControl,\n        meta: hasMeta,\n    }\n}\n\n// Parse a chord string (e.g. <c-s-p>) into textual descriptions of the relevant keys\n// <c-s-p> -> [\"control\", \"shift\", \"p\"]\nexport const parseChordParts = (keys: string): string[] => {\n    const parsedKeys = parseKeysFromVimString(keys)\n\n    if (!parsedKeys || !parsedKeys.chord || parsedKeys.chord.length === 0) {\n        return null\n    }\n\n    const firstChord = parsedKeys.chord[0]\n\n    const chordParts: string[] = []\n\n    if (firstChord.meta) {\n        chordParts.push(\"meta\")\n    }\n\n    if (firstChord.control) {\n        chordParts.push(\"control\")\n    }\n\n    if (firstChord.alt) {\n        chordParts.push(\"alt\")\n    }\n\n    if (firstChord.shift) {\n        chordParts.push(\"shift\")\n    }\n\n    chordParts.push(firstChord.character)\n\n    return chordParts\n}\n"
  },
  {
    "path": "browser/src/Input/Keyboard/KeyboardLayout.ts",
    "content": "import * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as Platform from \"./../../Platform\"\n\nexport interface IKeyMap {\n    [key: string]: IKeyInfo\n}\n\nexport interface IKeyInfo {\n    unmodified: string\n    withShift: string\n    withAltGraphShift?: string\n    withAltGraph?: string\n}\n\n// Helper method to augment the key mapping in cases\n// where it isn't accurate from `keyboard-layout`\nconst augmentKeyMap = (keyMap: IKeyMap, language: string): IKeyMap => {\n    // Temporary hack to workaround atom/keyboard-layout#36\n    if (Platform.isWindows() && language === \"es-ES\") {\n        // tslint:disable-next-line no-string-literal\n        keyMap[\"BracketLeft\"] = {\n            unmodified: null,\n            withShift: null,\n            withAltGraph: \"[\",\n            withAltGraphShift: null,\n        }\n    }\n\n    return keyMap\n}\n\nexport class KeyboardLayoutManager {\n    private _keyMap: IKeyMap = null\n    private _onKeyMapChanged: Event<void> = new Event<void>()\n\n    /**\n     * Event that is triggered when the keymap is changed,\n     * ie, when the keyboard layout is changed externally\n     */\n    public get onKeyMapChanged(): IEvent<void> {\n        return this._onKeyMapChanged\n    }\n\n    public getCurrentKeyMap(): IKeyMap {\n        if (!this._keyMap) {\n            const KeyboardLayout = require(\"keyboard-layout\") // tslint:disable-line no-var-requires\n            const keyboardLanguage = KeyboardLayout.getCurrentKeyboardLanguage()\n            Log.verbose(\"[Keyboard Layout] \" + KeyboardLayout.getCurrentKeyboardLayout())\n            this._keyMap = augmentKeyMap(KeyboardLayout.getCurrentKeymap(), keyboardLanguage)\n\n            // Lazily subscribe to the KeyboardLayout.onDidChangeCurrentKeyboardLayout\n            // This is lazy primarily for unit testing outside of electron (where this module isn't available)\n            KeyboardLayout.onDidChangeCurrentKeyboardLayout((newLayout: string) => {\n                Log.verbose(\"[Keyboard Layout] \" + newLayout)\n                this._keyMap = KeyboardLayout.getCurrentKeymap()\n                this._onKeyMapChanged.dispatch()\n            })\n        }\n\n        return this._keyMap\n    }\n}\n"
  },
  {
    "path": "browser/src/Input/Keyboard/KeyboardResolver.ts",
    "content": "/**\n * KeyboardResolver\n *\n * Manages set of resolvers, and adding/removing resolvers.\n */\nimport * as Log from \"oni-core-logging\"\nimport { IDisposable } from \"oni-types\"\n\nimport { KeyResolver } from \"./Resolvers\"\n\nexport class KeyboardResolver {\n    private _resolvers: KeyResolver[] = []\n\n    public addResolver(resolver: KeyResolver): IDisposable {\n        this._resolvers.push(resolver)\n        const dispose = () => {\n            this._resolvers = this._resolvers.filter(r => r !== resolver)\n        }\n\n        return {\n            dispose,\n        }\n    }\n\n    public resolveKeyEvent(evt: KeyboardEvent): string | null {\n        const mappedKey = this._resolvers.reduce((prev: string, current) => {\n            if (prev === null) {\n                return prev\n            } else {\n                return current(evt, prev)\n            }\n        }, evt.key)\n\n        if (Log.isDebugLoggingEnabled()) {\n            Log.debug(\n                `[Key event] Code: ${evt.code} Key: ${evt.key} CtrlKey: ${evt.ctrlKey} ShiftKey: ${\n                    evt.shiftKey\n                } AltKey: ${evt.altKey} | Resolution: ${mappedKey}`,\n            )\n        }\n\n        return mappedKey\n    }\n}\n"
  },
  {
    "path": "browser/src/Input/Keyboard/Resolvers.ts",
    "content": "import { IKeyInfo, IKeyMap, KeyboardLayoutManager } from \"./KeyboardLayout\"\n\n/**\n * Interface describing a 'key resolver' - a strategy\n * for resolving a keyboard event to a vim-facing input event.\n *\n * Key resolvers are intended to be chained together.\n *\n * If a key resolver returns null, it will prevent processing that key.\n */\nexport type KeyResolver = (evt: KeyboardEvent, previousResolution: string | null) => string | null\n\nconst keysToIgnore = [\n    \"Shift\",\n    \"Control\",\n    \"Alt\",\n    \"AltGraph\",\n    \"CapsLock\",\n    \"Pause\",\n    \"ScrollLock\",\n    \"AudioVolumeUp\",\n    \"AudioVolumeDown\",\n]\n\nexport const ignoreMetaKeyResolver = (\n    evt: KeyboardEvent,\n    previousResolution: string | null,\n): string | null => {\n    if (keysToIgnore.indexOf(evt.key) >= 0) {\n        return null\n    } else {\n        return evt.key\n    }\n}\n\nconst keysToRemap: { [key: string]: string } = {\n    Backspace: \"bs\",\n    Escape: \"esc\",\n    Enter: \"enter\",\n    Tab: \"tab\", // Tab\n    ArrowLeft: \"left\", // ArrowLeft\n    ArrowUp: \"up\", // ArrowUp\n    ArrowRight: \"right\", // ArrowRight\n    ArrowDown: \"down\", // ArrowDown\n    Insert: \"insert\",\n    \" \": \"space\",\n}\n\nexport const remapResolver = (\n    evt: KeyboardEvent,\n    previousResolution: string | null,\n): string | null => {\n    return keysToRemap[evt.key] ? keysToRemap[evt.key] : previousResolution\n}\n\nexport const getMetaKeyResolver = () => {\n    const keyboardLayout: KeyboardLayoutManager = new KeyboardLayoutManager()\n\n    let keyMap = keyboardLayout.getCurrentKeyMap()\n\n    keyboardLayout.onKeyMapChanged.subscribe(() => {\n        keyMap = keyboardLayout.getCurrentKeyMap()\n    })\n\n    return (evt: KeyboardEvent, previousResolution: string | null): null | string => {\n        const isCharacterFromShiftKey = isShiftCharacter(keyMap, evt)\n        const isCharacterFromAltGraphKey = isAltGraphCharacter(keyMap, evt)\n\n        let mappedKey = previousResolution\n\n        if (mappedKey === \"<\") {\n            mappedKey = \"lt\"\n        }\n\n        const metaPressed = evt.metaKey\n\n        let controlPressed = false\n        // On Windows, when the AltGr key is pressed, _both_\n        // the evt.ctrlKey and evt.altKey are set to true.\n        if (evt.ctrlKey && !isCharacterFromAltGraphKey) {\n            mappedKey = \"c-\" + previousResolution + \"\"\n            controlPressed = true\n            evt.preventDefault()\n        }\n\n        if (evt.shiftKey && (!isCharacterFromShiftKey || controlPressed || metaPressed)) {\n            mappedKey = \"s-\" + mappedKey\n        }\n\n        if (evt.altKey && !isCharacterFromAltGraphKey) {\n            mappedKey = \"a-\" + mappedKey\n            evt.preventDefault()\n        }\n\n        if (metaPressed) {\n            mappedKey = \"m-\" + mappedKey\n            evt.preventDefault()\n        }\n\n        if (mappedKey.length > 1) {\n            mappedKey = \"<\" + mappedKey.toLowerCase() + \">\"\n        }\n\n        return mappedKey\n    }\n}\n\nexport const createMetaKeyResolver = (keyMap: IKeyMap) => {\n    return (evt: KeyboardEvent, previousResolution: string | null): null | string => {\n        const isCharacterFromShiftKey = isShiftCharacter(keyMap, evt)\n        const isCharacterFromAltGraphKey = isAltGraphCharacter(keyMap, evt)\n\n        let mappedKey = previousResolution\n\n        if (mappedKey === \"<\") {\n            mappedKey = \"lt\"\n        }\n\n        const metaPressed = evt.metaKey\n\n        let controlPressed = false\n        // On Windows, when the AltGr key is pressed, _both_\n        // the evt.ctrlKey and evt.altKey are set to true.\n        if (evt.ctrlKey && !isCharacterFromAltGraphKey) {\n            mappedKey = \"c-\" + previousResolution + \"\"\n            controlPressed = true\n            evt.preventDefault()\n        }\n\n        if (evt.shiftKey && (!isCharacterFromShiftKey || controlPressed || metaPressed)) {\n            mappedKey = \"s-\" + mappedKey\n        }\n\n        if (evt.altKey && !isCharacterFromAltGraphKey) {\n            mappedKey = \"a-\" + mappedKey\n            evt.preventDefault()\n        }\n\n        if (metaPressed) {\n            mappedKey = \"m-\" + mappedKey\n            evt.preventDefault()\n        }\n\n        if (mappedKey.length > 1) {\n            mappedKey = \"<\" + mappedKey.toLowerCase() + \">\"\n        }\n\n        return mappedKey\n    }\n}\n\nconst isShiftCharacter = (keyMap: IKeyMap, evt: KeyboardEvent): boolean => {\n    const { key, code } = evt\n\n    const mappedKey: IKeyInfo = keyMap[code]\n\n    if (!mappedKey) {\n        return false\n    }\n\n    if (code === \"Space\") {\n        return false\n    }\n\n    if (mappedKey.withShift === key || mappedKey.withAltGraphShift === key) {\n        return true\n    } else {\n        return false\n    }\n}\n\nconst isAltGraphCharacter = (keyMap: IKeyMap, evt: KeyboardEvent): boolean => {\n    const { key, code } = evt\n\n    const mappedKey: IKeyInfo = keyMap[code]\n\n    if (!mappedKey) {\n        return false\n    }\n\n    if (mappedKey.withAltGraph === key || mappedKey.withAltGraphShift === key) {\n        return true\n    } else {\n        return false\n    }\n}\n"
  },
  {
    "path": "browser/src/Input/Keyboard/index.ts",
    "content": "export * from \"./Resolvers\"\nexport * from \"./KeyboardLayout\"\n"
  },
  {
    "path": "browser/src/Input/KeyboardInput.tsx",
    "content": "/**\n * KeyboardInput.tsx\n *\n * Specialized input control to handle IME & dead key cases\n *  - Allows enabling / disabling IME\n *  - Follows cursor\n *  - Invisible when not composing\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport { IDisposable, IEvent } from \"oni-types\"\n\nimport { IState } from \"./../Editor/NeovimEditor/NeovimEditorStore\"\nimport { focusManager } from \"./../Services/FocusManager\"\nimport { inputManager } from \"./../Services/InputManager\"\nimport { TypingPredictionManager } from \"./../Services/TypingPredictionManager\"\n\nimport { measureFont } from \"./../Font\"\n\ninterface IKeyboardInputViewProps extends IKeyboardInputProps {\n    top: number\n    left: number\n    height: number\n    foregroundColor: string\n    fontFamily: string\n    fontSize: string\n    fontCharacterWidthInPixels: number\n}\n\ninterface IKeyboardInputViewState {\n    /**\n     * Tracks if composition is occurring (ie, an IME is active)\n     */\n    isComposing: boolean\n\n    /**\n     * Tracks the width of the currently composing text.\n     * This isn't the same as the input text string value .length(),\n     * because usually for IMEs there are multi-byte characters.\n     */\n    compositionTextWidthInPixels: number\n}\n\nexport interface IKeyboardInputProps {\n    startActive?: boolean\n    onActivate: IEvent<void>\n\n    onKeyDown?: (key: string) => void\n    onImeStart?: () => void\n    onImeEnd?: () => void\n    typingPrediction?: TypingPredictionManager\n\n    // Optional methods for integrating animation,\n    // ie: 'cursor bounce':\n    onBounceStart?: () => void\n    onBounceEnd?: () => void\n}\n\n/**\n * KeyboardInput\n *\n * Helper for managing state and sanitizing input from dead keys, IME, etc\n */\nexport class KeyboardInputView extends React.PureComponent<\n    IKeyboardInputViewProps,\n    IKeyboardInputViewState\n> {\n    private _keyboardElement: HTMLInputElement\n    private _disposables: IDisposable[] = []\n\n    constructor(props: IKeyboardInputViewProps) {\n        super(props)\n\n        this.state = {\n            isComposing: false,\n            compositionTextWidthInPixels: 0,\n        }\n    }\n\n    public focus() {\n        this._keyboardElement.focus()\n    }\n\n    public componentDidMount(): void {\n        if (this.props.onActivate) {\n            this._removeExistingDisposables()\n            const d1 = this.props.onActivate.subscribe(() => {\n                focusManager.setFocus(this._keyboardElement)\n            })\n            this._disposables.push(d1)\n        }\n\n        if (this.props.startActive && this._keyboardElement) {\n            focusManager.setFocus(this._keyboardElement)\n        }\n    }\n\n    public componentWillUnmount(): void {\n        this._removeExistingDisposables()\n    }\n\n    public render(): JSX.Element {\n        const opacity = this.state.isComposing ? 0.8 : 0\n\n        const containerStyle: React.CSSProperties = {\n            position: \"absolute\",\n            top: this.props.top.toString() + \"px\",\n            left: this.props.left.toString() + \"px\",\n            height: this.props.height.toString() + \"px\",\n            right: \"0px\",\n            pointerEvents: \"none\",\n            opacity,\n            overflow: \"hidden\",\n            transform: \"translateZ(0px)\", // See #1129 - needed to keep it from re-rendering\n        }\n\n        const inputStyle: React.CSSProperties = {\n            position: \"absolute\",\n            padding: \"0px\",\n            width: \"100%\",\n            left: \"0px\",\n            right: \"0px\",\n            color: \"black\",\n            border: \"0px\",\n            outline: \"none\",\n            font: \"inherit\",\n            backgroundColor: \"transparent\",\n        }\n\n        const backgroundStyle: React.CSSProperties = {\n            position: \"absolute\",\n            height: \"100%\",\n            backgroundColor: \"white\",\n            left: \"0px\",\n            padding: \"2px\",\n            marginTop: \"-2px\",\n            marginLeft: \"-2px\",\n            width: this.state.compositionTextWidthInPixels + \"px\",\n        }\n\n        return (\n            <div style={containerStyle}>\n                <div style={backgroundStyle} />\n                <input\n                    style={inputStyle}\n                    ref={elem => (this._keyboardElement = elem)}\n                    type={\"text\"}\n                    onKeyDown={evt => this._onKeyDown(evt)}\n                    onKeyUp={evt => this._onKeyUp(evt)}\n                    onCompositionEnd={evt => this._onCompositionEnd(evt)}\n                    onCompositionUpdate={evt => this._onCompositionUpdate(evt)}\n                    onCompositionStart={evt => this._onCompositionStart(evt)}\n                    onInput={evt => this._onInput(evt)}\n                />\n            </div>\n        )\n    }\n\n    private _onKeyUp(evt: React.KeyboardEvent<HTMLInputElement>) {\n        if (this.props.onBounceEnd) {\n            this.props.onBounceEnd()\n        }\n    }\n\n    private _onKeyDown(evt: React.KeyboardEvent<HTMLInputElement>) {\n        // 'Process' means hand-off to the IME -\n        // so the composition events should handle this\n        if (evt.key === \"Process\" || evt.key === \"Dead\") {\n            return\n        }\n\n        if (this.state.isComposing) {\n            return\n        }\n\n        if (this.props.onBounceStart) {\n            this.props.onBounceStart()\n        }\n\n        const key = inputManager.resolvers.resolveKeyEvent(evt.nativeEvent)\n\n        if (!key) {\n            return\n        }\n\n        const isMetaCommand = key.length > 1 && key !== \"<lt>\"\n\n        // We'll let the `input` handler take care of it,\n        // unless it is a keystroke containing meta characters\n        if (isMetaCommand) {\n            this._commit(key)\n            evt.preventDefault()\n            return\n        } else {\n            if (this.props.typingPrediction) {\n                this.props.typingPrediction.addPrediction(key)\n            }\n        }\n    }\n\n    private _onCompositionStart(evt: React.CompositionEvent<HTMLInputElement>) {\n        if (this.props.onImeStart) {\n            this.props.onImeStart()\n        }\n\n        if (this.props.typingPrediction) {\n            this.props.typingPrediction.clearAllPredictions()\n        }\n\n        this.setState({\n            isComposing: true,\n        })\n    }\n\n    private _onCompositionUpdate(evt: React.CompositionEvent<HTMLInputElement>) {\n        if (this._keyboardElement) {\n            const measurements = measureFont(this.props.fontSize, this.props.fontFamily, evt.data)\n\n            // Add some padding for an extra character to the end of the input box\n            const roomForNextCharacter = this.props.fontCharacterWidthInPixels\n            const width = Math.ceil(measurements.width) + roomForNextCharacter\n\n            this.setState({\n                compositionTextWidthInPixels: width,\n            })\n        }\n    }\n\n    private _onCompositionEnd(evt: React.CompositionEvent<HTMLInputElement>) {\n        if (this.props.onImeEnd) {\n            this.props.onImeEnd()\n        }\n\n        if (this._keyboardElement) {\n            this._commit(this._keyboardElement.value)\n        }\n    }\n\n    private _onInput(evt: React.FormEvent<HTMLInputElement>) {\n        const valueLength = this._keyboardElement.value.length\n\n        if (!this.state.isComposing && valueLength > 0) {\n            this._commit(this._keyboardElement.value.replace(\"<\", \"<lt>\"))\n        }\n    }\n\n    private _commit(val: string): void {\n        this.setState({\n            isComposing: false,\n            compositionTextWidthInPixels: 0,\n        })\n\n        this._keyboardElement.value = \"\"\n        this.props.onKeyDown(val)\n    }\n\n    private _removeExistingDisposables(): void {\n        this._disposables.forEach(d => d.dispose())\n        this._disposables = []\n    }\n}\n\nconst mapStateToProps = (\n    state: IState,\n    originalProps: IKeyboardInputProps,\n): IKeyboardInputViewProps => {\n    return {\n        ...originalProps,\n        top: state.cursorPixelY,\n        left: state.cursorPixelX,\n        height: state.fontPixelHeight,\n        foregroundColor: state.colors[\"editor.foreground\"],\n        fontFamily: state.fontFamily,\n        fontSize: state.fontSize,\n        fontCharacterWidthInPixels: state.fontPixelWidth,\n    }\n}\n\nexport const KeyboardInput = connect(mapStateToProps)(KeyboardInputView)\n"
  },
  {
    "path": "browser/src/Input/Mouse.ts",
    "content": "import { EventEmitter } from \"events\"\n\nimport { IScreen } from \"./../neovim\"\n\nconst SCROLL_THRESHOLD_IN_PIXELS = 10\n\n// TODO\n// Handle modifier keys\nexport class Mouse extends EventEmitter {\n    private _isDragging = false\n    private _scrollDelta = 0\n\n    constructor(private _editorElement: HTMLDivElement, private _screen: IScreen) {\n        super()\n\n        this._editorElement.addEventListener(\"mousedown\", (evt: MouseEvent) => {\n            const { line, column } = this._convertEventToPosition(evt)\n\n            this.emit(\"mouse\", `<LeftMouse><${line},${column}>`)\n            this._isDragging = true\n        })\n\n        this._editorElement.addEventListener(\"mousemove\", (evt: MouseEvent) => {\n            const { line, column } = this._convertEventToPosition(evt)\n\n            if (this._isDragging) {\n                this.emit(\"mouse\", `<LeftDrag><${line},${column}>`)\n            }\n        })\n\n        this._editorElement.addEventListener(\"mouseup\", (evt: MouseEvent) => {\n            const { line, column } = this._convertEventToPosition(evt)\n\n            this.emit(\"mouse\", `<LeftRelease><${line},${column}>`)\n            this._isDragging = false\n        })\n\n        // The internet told me 'mousewheel' is deprecated and use this.\n        this._editorElement.addEventListener(\"wheel\", (evt: WheelEvent) => {\n            const { line, column } = this._convertEventToPosition(evt)\n            let scrollcmdY = `<`\n            if (evt.ctrlKey || evt.shiftKey) {\n                scrollcmdY += `C-` // The S- and C- prefixes have the same effect\n            }\n\n            const normalizedDelta = this._normalizeScrollDeltaToPixels(evt.deltaY, evt.deltaMode)\n            if (!normalizedDelta) {\n                return\n            }\n\n            this._isDragging = false\n            this._scrollDelta += normalizedDelta\n            if (this._scrollDeltaIsSignificant()) {\n                // This is 'less than' because I made this on a mac to behave just like\n                // the other applications I use. However, because OSX is super weird, it\n                // might be backwards.\n                if (this._scrollDelta < 0) {\n                    scrollcmdY += `ScrollWheelUp>`\n                } else {\n                    scrollcmdY += `ScrollWheelDown>`\n                }\n                this._scrollDelta = 0\n                this.emit(\"mouse\", scrollcmdY + `<${line},${column}>`)\n            }\n        })\n    }\n\n    private _normalizeScrollDeltaToPixels(delta: number, deltaMode: number): number {\n        switch (deltaMode) {\n            case WheelEvent.DOM_DELTA_PIXEL:\n                return delta\n            case WheelEvent.DOM_DELTA_LINE:\n                return delta * this._screen.fontHeightInPixels\n            case WheelEvent.DOM_DELTA_PAGE:\n                return delta * this._screen.fontHeightInPixels * this._screen.height\n            default:\n                return delta\n        }\n    }\n\n    private _convertEventToPosition(evt: MouseEvent): { line: number; column: number } {\n        const mouseX = evt.offsetX\n        const mouseY = evt.offsetY\n\n        return {\n            line: Math.floor(mouseX / this._screen.fontWidthInPixels),\n            column: Math.floor(mouseY / this._screen.fontHeightInPixels),\n        }\n    }\n\n    private _scrollDeltaIsSignificant(): boolean {\n        return Math.abs(this._scrollDelta) >= SCROLL_THRESHOLD_IN_PIXELS\n    }\n}\n"
  },
  {
    "path": "browser/src/Performance.ts",
    "content": "/**\n * Thin wrapper around browser performance API\n */\nexport function mark(markerName: string): void {\n    if (typeof window === \"undefined\") {\n        return\n    }\n\n    if (process.env.NODE_ENV === \"production\") {\n        return\n    }\n\n    performance.mark(markerName)\n\n    const anyConsole: any = console\n    anyConsole.timeStamp(markerName)\n\n    console.log(`[PERFORMANCE] ${markerName}: ${performance.now()}`) // tslint:disable-line no-console\n}\n\nexport const startMeasure = (measurementName: string): void => {\n    console.time(measurementName) // tslint:disable-line\n}\n\nexport const endMeasure = (measurementName: string): void => {\n    console.timeEnd(measurementName) // tslint:disable-line\n}\n"
  },
  {
    "path": "browser/src/PeriodicJobs.ts",
    "content": "import * as Log from \"oni-core-logging\"\nimport * as Constants from \"./Constants\"\n\n// IPeriodicJob implements the interface for a long-running job\n// that would be expensive to run synchronously, so it is\n// spread across multiple asynchronous iterations.\nexport interface IPeriodicJob {\n    // Execute should return `true` if the job is complete,\n    // false otherwise\n    execute(): boolean\n}\n\nexport class PeriodicJobManager {\n    private _currentScheduledJob: number = null\n    private _pendingJobs: IPeriodicJob[] = []\n\n    public startJob(job: IPeriodicJob) {\n        this._pendingJobs.push(job)\n        Log.verbose(\"[PeriodicJobManager]::startJob - \" + this._pendingJobs.length + \" total jobs.\")\n        this._scheduleJobs()\n    }\n\n    private _scheduleJobs(): void {\n        if (this._currentScheduledJob) {\n            return\n        }\n\n        if (this._pendingJobs.length === 0) {\n            Log.verbose(\"[PeriodicJobManager]::_scheduleJobs - no jobs pending.\")\n        }\n\n        this._currentScheduledJob = window.setTimeout(() => {\n            const completed = this._executePendingJobs()\n            window.clearTimeout(this._currentScheduledJob)\n            this._currentScheduledJob = null\n\n            if (!completed) {\n                this._scheduleJobs()\n            }\n        }, Constants.Delay.INSTANT)\n\n        Log.verbose(\"[PeriodicJobManager]::_scheduleJobs - \" + this._currentScheduledJob)\n    }\n\n    private _executePendingJobs(): boolean {\n        const completedJobs: IPeriodicJob[] = []\n        this._pendingJobs.forEach(job => {\n            const completed = job.execute()\n\n            if (completed) {\n                completedJobs.push(job)\n            }\n        })\n\n        // Remove completed jobs\n        this._pendingJobs = this._pendingJobs.filter(job => completedJobs.indexOf(job) === -1)\n\n        if (this._pendingJobs.length === 0) {\n            Log.verbose(\"[PeriodicJobManager] All jobs complete.\")\n        } else {\n            Log.verbose(\"[PeriodicJobManager] \" + this._pendingJobs.length + \" jobs remaining.\")\n        }\n\n        // Return true if all jobs were completed, false otherwise\n        return this._pendingJobs.length === 0\n    }\n}\n"
  },
  {
    "path": "browser/src/PersistentStore.ts",
    "content": "/**\n * Store.ts\n *\n * Abstraction for a persistent data store, that supports versioning and upgrade.\n */\n\nimport { remote } from \"electron\"\n\nimport * as Log from \"oni-core-logging\"\n\n// We need to use the 'main process' version of electron-settings.\n// See: https://github.com/nathanbuchar/electron-settings/wiki/FAQs\nconst PersistentSettings = remote.require(\"electron-settings\")\n\nexport interface IPersistentStore<T> {\n    get(): Promise<T>\n    set(value: T): Promise<void>\n    delete(key: string): Promise<T>\n    has(key: string): boolean\n}\n\nexport const getPersistentStore = <T>(\n    storeIdentifier: string,\n    defaultValue: T,\n    currentVersion: number = 0,\n): IPersistentStore<T> => {\n    return new PersistentStore<T>(storeIdentifier, defaultValue, currentVersion)\n}\n\nexport interface IPersistedValueWithMetadata<T> {\n    schemaVersion: number\n    value: T\n}\n\nexport class PersistentStore<T> implements IPersistentStore<T> {\n    private _currentValue: IPersistedValueWithMetadata<T> = null\n\n    constructor(\n        private _storeKey: string,\n        private _defaultValue: T,\n        private _currentVersion: number,\n    ) {\n        let val = null\n        try {\n            val = JSON.parse(PersistentSettings.get(this._storeKey))\n        } catch (ex) {\n            Log.warn(\"Error deserializing from store: \" + ex)\n        }\n\n        this._currentValue = val\n\n        if (!this._currentValue) {\n            this._currentValue = {\n                value: this._defaultValue,\n                schemaVersion: this._currentVersion,\n            }\n        }\n\n        // TODO: Check if _currentVersion is ahead of the value,\n        // if so, upgrade\n    }\n\n    public async get(): Promise<T> {\n        return this._currentValue.value\n    }\n\n    public async set(val: T): Promise<void> {\n        this._currentValue = {\n            value: val,\n            schemaVersion: this._currentVersion,\n        }\n\n        PersistentSettings.set(this._storeKey, JSON.stringify(this._currentValue))\n    }\n\n    public has(key: string) {\n        return PersistentSettings.has(key)\n    }\n\n    public async delete(key: string) {\n        return PersistentSettings.delete(`${this._storeKey}.${key}`)\n    }\n}\n"
  },
  {
    "path": "browser/src/Platform.ts",
    "content": "import * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nexport const isWindows = () => os.platform() === \"win32\"\nexport const isMac = () => os.platform() === \"darwin\"\nexport const isLinux = () => os.platform() === \"linux\"\n\nexport const getUserHome = () => (isWindows() ? process.env[\"APPDATA\"] : process.env[\"HOME\"]) // tslint:disable-line no-string-literal\n\nexport const getLinkPath = () => (isMac() ? \"/usr/local/bin/oni\" : \"\") // TODO: Linux\nexport const isAddedToPath = () => {\n    if (isMac()) {\n        try {\n            fs.lstatSync(getLinkPath())\n\n            const currentLinkPath = fs.readlinkSync(getLinkPath())\n\n            // Temporary guard to check if the old script has been linked to.\n            if (currentLinkPath.indexOf(\"cli/mac/oni.sh\") === -1) {\n                return false\n            }\n        } catch (_) {\n            return false\n        }\n        return true\n    }\n\n    return false\n}\nexport const removeFromPath = () => (isMac() ? fs.unlinkSync(getLinkPath()) : false) // TODO: Linux\n\nexport const addToPath = async () => {\n    if (isMac()) {\n        const appDirectory = path.join(path.dirname(process.mainModule.filename), \"..\", \"..\")\n        const options = { name: \"Oni\", icns: path.join(appDirectory, \"Resources\", \"Oni.icns\") }\n        const linkPath = path.join(appDirectory, \"Resources\", \"app\", \"cli\", \"mac\", \"oni.sh\")\n        await _runSudoCommand(`ln -fs ${linkPath} ${getLinkPath()}`, options)\n    }\n}\n\nconst _runSudoCommand = async (command: string, options: any) => {\n    const sudo = await import(\"sudo-prompt\")\n    return new Promise(resolve => {\n        sudo.exec(command, options, (error: Error, stdout: string, stderr: string) => {\n            resolve({ error, stdout, stderr })\n        })\n    })\n}\n"
  },
  {
    "path": "browser/src/Plugins/AnonymousPlugin.ts",
    "content": "/**\n * AnonymousPlugin.ts\n *\n * Provides a globally-available, immediately-active plugin\n * Useful for testing the plugin API\n */\n\nimport * as OniApi from \"oni-api\"\n\nimport { Oni } from \"./Api/Oni\"\n\nexport class AnonymousPlugin {\n    private _oni: OniApi.Plugin.Api\n\n    public get oni(): OniApi.Plugin.Api {\n        return this._oni\n    }\n\n    constructor() {\n        this._oni = new Oni() // tslint:disable-line no-empty\n        window[\"Oni\"] = this._oni // tslint:disable-line no-string-literal\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/Capabilities.ts",
    "content": "/**\n * Capabilities.ts\n *\n * Export utility types / functions for working with plugin capabilities\n */\n\nexport interface IContributions {\n    commands: ICommandContribution[]\n    languages: ILanguageContribution[]\n    themes: IThemeContribution[]\n    iconThemes: IIconThemeContribution[]\n    snippets: ISnippetContribution[]\n}\n\nexport const DefaultContributions: IContributions = {\n    commands: [],\n    themes: [],\n    iconThemes: [],\n    snippets: [],\n    languages: [],\n}\n\nexport interface ICommandContribution {\n    command: string /* ie, myExtension.myCommand */\n    title: string /* My Extension Command */\n    category: string /* Testing */\n}\n\nexport interface IIconThemeContribution {\n    id: string\n    label: string\n    path: string\n}\n\nexport interface ILanguageContribution {\n    id: string\n    extensions: string[]\n}\n\nexport interface ISnippetContribution {\n    language: string\n    path: string\n}\n\nexport interface IThemeContribution {\n    name: string\n    path: string\n}\n\nexport interface IPluginMetadata {\n    name: string\n    main: string\n    engines: any\n    contributes: IContributions\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/LanguageClient/LanguageClientHelpers.ts",
    "content": "/**\n * LanguageClientHelpers.ts\n */\n\nimport * as os from \"os\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as Utility from \"./../../../Utility\"\n\nexport namespace TextDocumentSyncKind {\n    export const None = 0\n    export const Full = 1\n    export const Incremental = 2\n}\n\nexport interface CompletionOptions {\n    /**\n     * The server provides support to resolve additional\n     * information for a completion item.\n     */\n    resolveProvider?: boolean\n\n    /**\n     * The characters that trigger completion automatically.\n     */\n    triggerCharacters?: string[]\n}\n\n// ServerCapabilities\n// Defined in the LSP protocol: https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md\nexport interface ServerCapabilities {\n    completionProvider?: CompletionOptions\n    textDocumentSync?: number\n    documentSymbolProvider?: boolean\n}\n\nexport const wrapPathInFileUri = (path: string) => getFilePrefix() + Utility.normalizePath(path)\n\nexport const unwrapFileUriPath = (uri: string) => decodeURIComponent(uri.split(getFilePrefix())[1])\n\nexport const getTextFromContents = (\n    contents: types.MarkedString | types.MarkupContent | types.MarkedString[],\n): IMarkedStringResult[] => {\n    if (contents instanceof Array) {\n        return contents.map(markedString => getTextFromMarkedString(markedString))\n    }\n    const text = isMarkupContent(contents) ? getDocumentationText(contents) : contents\n    return [getTextFromMarkedString(text)]\n}\n\nexport const pathToTextDocumentIdentifierParms = (path: string) => ({\n    textDocument: {\n        uri: wrapPathInFileUri(path),\n    },\n})\n\nexport const pathToTextDocumentItemParams = (\n    path: string,\n    language: string,\n    text: string,\n    version: number,\n) => ({\n    textDocument: {\n        uri: wrapPathInFileUri(path),\n        languageId: language,\n        text,\n        version,\n    },\n})\n\nexport const eventContextToCodeActionParams = (filePath: string, range: types.Range) => {\n    const emptyDiagnostics: types.Diagnostic[] = []\n    return {\n        textDocument: {\n            uri: wrapPathInFileUri(filePath),\n        },\n        range,\n        context: { diagnostics: emptyDiagnostics },\n    }\n}\n\nexport const createTextDocumentPositionParams = (\n    filePath: string,\n    line: number,\n    column: number,\n) => ({\n    textDocument: {\n        uri: wrapPathInFileUri(filePath),\n    },\n    position: {\n        line,\n        character: column,\n    },\n})\n\nexport const bufferToTextDocumentPositionParams = (buffer: Oni.Buffer) => {\n    return createTextDocumentPositionParams(\n        buffer.filePath,\n        buffer.cursor.line,\n        buffer.cursor.column,\n    )\n}\n\nexport const createDidChangeTextDocumentParams = (\n    bufferFullPath: string,\n    lines: string[],\n    version: number,\n) => {\n    const text = lines.join(os.EOL)\n\n    return {\n        textDocument: {\n            uri: wrapPathInFileUri(bufferFullPath),\n            version,\n        },\n        contentChanges: [\n            {\n                text,\n            },\n        ],\n    }\n}\n\ninterface IMarkedStringResult {\n    value: string\n    language: string\n}\n\nconst getTextFromMarkedString = (markedString: types.MarkedString): IMarkedStringResult => {\n    if (typeof markedString === \"string\") {\n        return {\n            language: null,\n            value: markedString,\n        }\n    } else {\n        return {\n            // Split the language as it passed as e.g. \"reason.hover.type\"\n            language: markedString.language ? markedString.language.split(\".\")[0] : null,\n            value: markedString.value,\n        }\n    }\n}\n\nconst getFilePrefix = () => {\n    if (process.platform === \"win32\") {\n        return \"file:///\"\n    } else {\n        return \"file://\"\n    }\n}\n\nexport function isMarkupContent(input: any): input is types.MarkupContent {\n    return typeof input === \"object\" && input !== null && \"value\" in input && \"kind\" in input\n}\n\nexport const getDocumentationText = (documentation: string | types.MarkupContent) => {\n    // Documentation can be a string or an object specifying the documentations type as well as the value.\n    if (typeof documentation === \"string\") {\n        return documentation\n    }\n    return documentation.value\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/LanguageClient/LanguageClientLogger.ts",
    "content": "/**\n * LanguageClientLogger.ts\n *\n * Helper utility for handling logging from language service clients\n */\n\nimport * as Log from \"oni-core-logging\"\n\nexport class LanguageClientLogger {\n    public error(message: string): void {\n        Log.error(message)\n    }\n\n    public warn(message: string): void {\n        Log.warn(message)\n    }\n\n    public info(message: string): void {\n        Log.info(message)\n    }\n\n    public log(message: string): void {\n        Log.info(message)\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/Oni.ts",
    "content": "/**\n * OniApi.ts\n *\n * Implementation of OniApi's API surface\n * TODO: Gradually move over to `oni-api`\n */\n\nimport * as ChildProcess from \"child_process\"\n\nimport * as OniApi from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport Process from \"./Process\"\nimport { Services } from \"./Services\"\nimport { Ui } from \"./Ui\"\n\nimport { getInstance as getPluginsManagerInstance } from \"./../PluginManager\"\n\nimport { automation } from \"./../../Services/Automation\"\nimport { Colors, getInstance as getColors } from \"./../../Services/Colors\"\nimport { commandManager } from \"./../../Services/CommandManager\"\nimport { getInstance as getCompletionProvidersInstance } from \"./../../Services/Completion/CompletionProviders\"\nimport { configuration } from \"./../../Services/Configuration\"\nimport { getInstance as getDiagnosticsInstance } from \"./../../Services/Diagnostics\"\nimport { editorManager } from \"./../../Services/EditorManager\"\nimport { inputManager } from \"./../../Services/InputManager\"\nimport * as LanguageManager from \"./../../Services/Language\"\nimport { getTutorialManagerInstance } from \"./../../Services/Learning\"\nimport { getInstance as getAchievementsInstance } from \"./../../Services/Learning/Achievements\"\nimport { getInstance as getMenuManagerInstance } from \"./../../Services/Menu\"\nimport { getInstance as getFiltersInstance } from \"./../../Services/Menu/Filter\"\nimport { getInstance as getNotificationsInstance } from \"./../../Services/Notifications\"\nimport { getInstance as getOverlayInstance } from \"./../../Services/Overlay\"\nimport { recorder } from \"./../../Services/Recorder\"\nimport { getInstance as getSessionManagerInstance, SessionManager } from \"./../../Services/Sessions\"\nimport { getInstance as getSidebarInstance } from \"./../../Services/Sidebar\"\nimport { getInstance as getSneakInstance } from \"./../../Services/Sneak\"\nimport { getInstance as getSnippetsInstance } from \"./../../Services/Snippets\"\nimport { getInstance as getStatusBarInstance } from \"./../../Services/StatusBar\"\nimport { getInstance as getTokenColorsInstance } from \"./../../Services/TokenColors\"\nimport { windowManager } from \"./../../Services/WindowManager\"\nimport { getInstance as getWorkspaceInstance } from \"./../../Services/Workspace\"\n\nimport { Search } from \"./../../Services/Search/SearchProvider\"\n\nimport * as throttle from \"lodash/throttle\"\n\nconst react = require(\"react\") // tslint:disable-line no-var-requires\n\nexport class Dependencies {\n    public get React(): any {\n        return react\n    }\n}\n\nconst helpers = {\n    throttle,\n}\n\n/**\n * API instance for interacting with OniApi (and vim)\n */\nexport class Oni implements OniApi.Plugin.Api {\n    private _dependencies: Dependencies\n    private _ui: Ui\n    private _services: Services\n\n    public get achievements(): any /* TODO: Promote to API */ {\n        return getAchievementsInstance()\n    }\n\n    public get automation(): OniApi.Automation.Api {\n        return automation\n    }\n\n    public get colors(): Colors /* TODO: Promote to API */ {\n        return getColors()\n    }\n\n    public get commands(): OniApi.Commands.Api {\n        return commandManager\n    }\n\n    public get contextMenu(): any {\n        return null\n    }\n\n    public get log(): OniApi.Log {\n        return Log\n    }\n\n    public get plugins(): any {\n        return getPluginsManagerInstance()\n    }\n\n    public get recorder(): any {\n        return recorder\n    }\n\n    public get completions(): any {\n        return getCompletionProvidersInstance()\n    }\n\n    public get configuration(): OniApi.Configuration {\n        return configuration\n    }\n\n    public get diagnostics(): OniApi.Plugin.Diagnostics.Api {\n        return getDiagnosticsInstance()\n    }\n\n    public get dependencies(): Dependencies {\n        return this._dependencies\n    }\n\n    public get editors(): OniApi.EditorManager {\n        return editorManager\n    }\n\n    public get input(): OniApi.Input.InputManager {\n        return inputManager\n    }\n\n    public get language(): any {\n        return LanguageManager.getInstance()\n    }\n\n    public get menu(): any /* TODO */ {\n        return getMenuManagerInstance()\n    }\n\n    public get filter(): OniApi.Menu.IMenuFilters {\n        return getFiltersInstance(\"\") // TODO: Pass either \"core\" or plugin's name\n    }\n\n    public get notifications(): OniApi.Notifications.Api {\n        return getNotificationsInstance()\n    }\n\n    public get overlays(): OniApi.Overlays.Api {\n        return getOverlayInstance()\n    }\n\n    public get process(): OniApi.Process {\n        return Process\n    }\n\n    public get sidebar(): any {\n        return getSidebarInstance()\n    }\n\n    public get sneak(): any {\n        return getSneakInstance()\n    }\n\n    public get snippets(): OniApi.Snippets.SnippetManager {\n        return getSnippetsInstance()\n    }\n\n    public get statusBar(): OniApi.StatusBar {\n        return getStatusBarInstance()\n    }\n\n    public get tokenColors(): any {\n        return getTokenColorsInstance()\n    }\n\n    public get ui(): Ui {\n        return this._ui\n    }\n\n    public get sessions(): SessionManager {\n        return getSessionManagerInstance()\n    }\n\n    public get services(): Services {\n        return this._services\n    }\n\n    public get tutorials(): any /* todo */ {\n        return getTutorialManagerInstance()\n    }\n\n    public get windows(): OniApi.IWindowManager {\n        return windowManager as any\n    }\n\n    public get workspace(): OniApi.Workspace.Api {\n        return getWorkspaceInstance()\n    }\n\n    public get helpers() {\n        return helpers\n    }\n\n    public get search(): OniApi.Search.ISearch {\n        return new Search()\n    }\n\n    constructor() {\n        this._dependencies = new Dependencies()\n        this._ui = new Ui(react)\n        this._services = new Services()\n    }\n\n    public getActiveSection() {\n        const isInsertOrCommandMode = () => {\n            return (\n                this.editors.activeEditor.mode === \"insert\" ||\n                this.editors.activeEditor.mode === \"cmdline_normal\"\n            )\n        }\n        switch (true) {\n            case this.menu.isMenuOpen():\n                return \"menu\"\n            case this.sidebar && this.sidebar.isFocused:\n                return this.sidebar.activeEntryId\n            case isInsertOrCommandMode():\n                return \"commandline\"\n            default:\n                return \"editor\"\n        }\n    }\n\n    public populateQuickFix(entries: OniApi.QuickFixEntry[]): void {\n        const neovim: any = editorManager.activeEditor.neovim\n        neovim.quickFix.setqflist(entries, \"Search Results\")\n        neovim.command(\":copen\")\n    }\n\n    public async execNodeScript(\n        scriptPath: string,\n        args: string[] = [],\n        options: ChildProcess.ExecOptions = {},\n        callback: (err: any, stdout: string, stderr: string) => void,\n    ): Promise<ChildProcess.ChildProcess> {\n        Log.warn(\n            \"WARNING: `OniApi.execNodeScript` is deprecated. Please use `OniApi.process.execNodeScript` instead\",\n        )\n\n        return Process.execNodeScript(scriptPath, args, options, callback)\n    }\n\n    /**\n     * Wrapper around `child_process.exec` to run using electron as opposed to node\n     */\n    public async spawnNodeScript(\n        scriptPath: string,\n        args: string[] = [],\n        options: ChildProcess.SpawnOptions = {},\n    ): Promise<ChildProcess.ChildProcess> {\n        Log.warn(\n            \"WARNING: `OniApi.spawnNodeScript` is deprecated. Please use `OniApi.process.spawnNodeScript` instead\",\n        )\n\n        return Process.spawnNodeScript(scriptPath, args, options)\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/Process.ts",
    "content": "import * as ChildProcess from \"child_process\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport * as Platform from \"./../../Platform\"\nimport { configuration } from \"./../../Services/Configuration\"\n\nexport interface IShellEnvironmentFetcher {\n    getEnvironmentVariables(): Promise<any>\n}\n\ninterface IShellEnv {\n    default: {\n        sync: (shell?: string) => NodeJS.ProcessEnv\n    }\n}\n\nexport class ShellEnvironmentFetcher implements IShellEnvironmentFetcher {\n    private _shellEnvPromise: Promise<any>\n    private _shellEnv: IShellEnv\n\n    constructor() {\n        // Dynamic imports return { default: Module }\n        this._shellEnvPromise = import(\"shell-env\")\n    }\n\n    public async getEnvironmentVariables(): Promise<NodeJS.ProcessEnv> {\n        if (!this._shellEnv) {\n            this._shellEnv = await this._shellEnvPromise\n        }\n        try {\n            const userShell = configuration.getValue<string>(\"oni.userShell\")\n            const shell = typeof userShell === \"string\" ? userShell : undefined\n            const env = this._shellEnv.default.sync(shell)\n            return env\n        } catch (error) {\n            Log.warn(\n                `[Oni environment fetcher]: unable to get enviroment variables because: ${\n                    error.message\n                }`,\n            )\n        }\n        return {}\n    }\n}\n\nexport class Process implements Oni.Process {\n    public _spawnedProcessIds: number[] = []\n    private _env: NodeJS.ProcessEnv\n\n    constructor(\n        private _shellEnvironmentFetcher: IShellEnvironmentFetcher = new ShellEnvironmentFetcher(),\n    ) {}\n\n    public getPathSeparator = () => {\n        return Platform.isWindows() ? \";\" : \":\"\n    }\n\n    public mergePathEnvironmentVariable = (currentPath: string, pathsToAdd: string[]): string => {\n        if (!pathsToAdd || !pathsToAdd.length) {\n            return currentPath\n        }\n\n        const separator = this.getPathSeparator()\n\n        const joinedPathsToAdd = pathsToAdd.join(separator)\n\n        return currentPath + separator + joinedPathsToAdd\n    }\n\n    /**\n     * API surface area responsible for handling process-related tasks\n     * (spawning processes, managing running process, etc)\n     */\n    public execNodeScript = async (\n        scriptPath: string,\n        args: string[] = [],\n        options: ChildProcess.ExecOptions = {},\n        callback: (err: any, stdout: string, stderr: string) => void,\n    ): Promise<ChildProcess.ChildProcess> => {\n        const spawnOptions = await this.mergeSpawnOptions(options)\n        spawnOptions.env.ELECTRON_RUN_AS_NODE = 1\n\n        const execOptions = [process.execPath, scriptPath].concat(args)\n        const execString = execOptions.map(s => `\"${s}\"`).join(\" \")\n\n        const proc = ChildProcess.exec(execString, spawnOptions, callback)\n        this._spawnedProcessIds.push(proc.pid)\n        return proc\n    }\n\n    /**\n     * Get the set of process IDs that were spawned by Oni\n     */\n    public getPIDs = (): number[] => {\n        return [...this._spawnedProcessIds]\n    }\n\n    /**\n     * Get the __dirname of currently executing file\n     */\n    public getDirname = () => {\n        return __dirname\n    }\n\n    /**\n     * Wrapper around `child_process.exec` to run using electron as opposed to node\n     */\n    public spawnNodeScript = async (\n        scriptPath: string,\n        args: string[] = [],\n        options: ChildProcess.SpawnOptions = {},\n    ): Promise<ChildProcess.ChildProcess> => {\n        const spawnOptions = await this.mergeSpawnOptions(options)\n        spawnOptions.env.ELECTRON_RUN_AS_NODE = 1\n\n        const allArgs = [scriptPath].concat(args)\n\n        const proc = ChildProcess.spawn(process.execPath, allArgs, spawnOptions)\n        this._spawnedProcessIds.push(proc.pid)\n        return proc\n    }\n\n    /**\n     * Spawn process - wrapper around `child_process.spawn`\n     */\n    public spawnProcess = async (\n        startCommand: string,\n        args: string[] = [],\n        options: ChildProcess.SpawnOptions = {},\n    ): Promise<ChildProcess.ChildProcess> => {\n        const spawnOptions = await this.mergeSpawnOptions(options)\n\n        const proc = ChildProcess.spawn(startCommand, args, spawnOptions)\n        this._spawnedProcessIds.push(proc.pid)\n        proc.on(\"error\", (err: Error) => {\n            Log.error(err)\n        })\n\n        return proc\n    }\n\n    public mergeSpawnOptions = async (\n        originalSpawnOptions: ChildProcess.ExecOptions | ChildProcess.SpawnOptions,\n    ): Promise<any> => {\n        let existingPath: string\n\n        try {\n            if (!this._env) {\n                this._env = await this._shellEnvironmentFetcher.getEnvironmentVariables()\n            }\n            existingPath = process.env.Path || process.env.PATH\n        } catch (e) {\n            existingPath = process.env.Path || process.env.PATH\n        }\n\n        const additionalEnvironmentVariables =\n            configuration.getValue(\"environment.additionalVariables\") || {}\n\n        const requiredOptions = {\n            env: {\n                ...process.env,\n                ...this._env,\n                ...originalSpawnOptions.env,\n                ...additionalEnvironmentVariables,\n            },\n        }\n\n        // TODO: Workaround for the bug fix here:\n        // https://github.com/neovim/neovim/pull/9345\n        // Once 0.3.2 is available and we've switched, we won't need this anymore.\n        if (Platform.isMac() && !requiredOptions.env.LANG) {\n            requiredOptions.env.LANG = \"en_us.UTF-8\"\n            Log.warn(\n                \"'LANG' environment variable not set, using default value of 'en_us.UTF-8'. Consider setting environment.additionalVariables['LANG'].\",\n            )\n        }\n\n        requiredOptions.env.PATH = this.mergePathEnvironmentVariable(\n            existingPath,\n            configuration.getValue(\"environment.additionalPaths\"),\n        )\n\n        return {\n            ...originalSpawnOptions,\n            ...requiredOptions,\n        }\n    }\n}\n\nexport default new Process()\n"
  },
  {
    "path": "browser/src/Plugins/Api/Services.ts",
    "content": "import { getInstance, VersionControlManager } from \"./../../Services/VersionControl\"\n\nexport class Services {\n    public get vcs(): VersionControlManager {\n        return getInstance()\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/Ui.ts",
    "content": "import * as Oni from \"oni-api\"\n\nimport { getFileIcon } from \"../../Services/FileIcon\"\nimport { getInstance } from \"../../Services/IconThemes\"\nimport { Icon, IconProps, IconSize } from \"../../UI/Icon\"\n\nexport class Ui implements Oni.Ui.IUi {\n    constructor(private _react: any) {}\n\n    public createIcon(props: IconProps): any {\n        return this._react.createElement(Icon, props)\n    }\n\n    public getIconClassForFile(filename: string, language?: string): string {\n        const Icons = getInstance()\n        return Icons.getIconClassForFile(filename, language)\n    }\n\n    public getFileIcon(fileName: string): any {\n        return getFileIcon(fileName)\n    }\n\n    public get iconSize(): any {\n        return IconSize\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/Api/shell-env.d.ts",
    "content": "declare module \"shell-env\" {\n    export namespace shellEnv {\n        export function sync(shell?: string): NodeJS.Env\n        export default function(shell?: string): Promise<NodeJS.Env>\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/PackageMetadataParser.ts",
    "content": "/**\n * PackageMetadataParser.ts\n *\n * Responsible for parsing and normalizing package.json for ONI plugins\n */\n\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as Capabilities from \"./Api/Capabilities\"\n\nconst remapToAbsolutePaths = (\n    packageRoot: string,\n    contributes: Capabilities.IContributions,\n): Capabilities.IContributions => {\n    const remapThemePath = (\n        themes: Capabilities.IThemeContribution,\n    ): Capabilities.IThemeContribution => {\n        return {\n            ...themes,\n            path: path.join(packageRoot, themes.path),\n        }\n    }\n\n    const remapIconPath = (\n        iconThemes: Capabilities.IIconThemeContribution,\n    ): Capabilities.IIconThemeContribution => {\n        return {\n            ...iconThemes,\n            path: path.join(packageRoot, iconThemes.path),\n        }\n    }\n\n    const remapSnippetPath = (\n        snippet: Capabilities.ISnippetContribution,\n    ): Capabilities.ISnippetContribution => {\n        return {\n            ...snippet,\n            path: path.join(packageRoot, snippet.path),\n        }\n    }\n\n    return {\n        ...contributes,\n        themes: contributes.themes.map(t => remapThemePath(t)),\n        iconThemes: contributes.iconThemes.map(it => remapIconPath(it)),\n        snippets: contributes.snippets.map(s => remapSnippetPath(s)),\n    }\n}\n\nexport const readMetadata = (packagePath: string): Capabilities.IPluginMetadata | null => {\n    const packageContents = fs.readFileSync(packagePath, \"utf8\")\n\n    let metadata: Capabilities.IPluginMetadata = null\n    try {\n        metadata = JSON.parse(packageContents) as Capabilities.IPluginMetadata\n    } catch (ex) {\n        Log.error(ex)\n    }\n\n    if (!metadata) {\n        return null\n    }\n\n    // tslint:disable-next-line no-string-literal\n    if (!metadata.engines || !metadata.engines[\"oni\"]) {\n        Log.warn(\"Aborting plugin load as Oni engine version not specified\")\n        return null\n    }\n\n    const contributes = {\n        ...Capabilities.DefaultContributions,\n        ...metadata.contributes,\n    }\n\n    return {\n        ...metadata,\n        contributes: remapToAbsolutePaths(path.dirname(packagePath), contributes),\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/Plugin.ts",
    "content": "import * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as Capabilities from \"./Api/Capabilities\"\nimport { Oni } from \"./Api/Oni\"\n\nimport * as PackageMetadataParser from \"./PackageMetadataParser\"\n\nexport class Plugin {\n    private _oniPluginMetadata: Capabilities.IPluginMetadata\n    private _oni: Oni\n    private _id: string\n    private _instance: any\n\n    public get id(): string {\n        return this._id\n    }\n\n    public get instance(): any {\n        return this._instance\n    }\n\n    public get metadata(): Capabilities.IPluginMetadata {\n        return this._oniPluginMetadata\n    }\n\n    public get source(): string {\n        return this._source\n    }\n\n    public get name(): string | null {\n        const metadata = this.metadata\n        return metadata === null || metadata === undefined ? null : metadata.name\n    }\n\n    constructor(private _pluginRootDirectory: string, private _source: string) {\n        const packageJsonPath = path.join(this._pluginRootDirectory, \"package.json\")\n\n        this._id = path.basename(this._pluginRootDirectory)\n\n        if (fs.existsSync(packageJsonPath)) {\n            this._oniPluginMetadata = PackageMetadataParser.readMetadata(packageJsonPath)\n        }\n    }\n\n    public activate(): void {\n        if (!this._oniPluginMetadata || !this._oniPluginMetadata.main) {\n            return\n        }\n\n        this._oni = new Oni()\n        const vm = require(\"vm\")\n        Log.info(`[PLUGIN] Activating: ${this._oniPluginMetadata.name}`)\n\n        let moduleEntryPoint = path.normalize(\n            path.join(this._pluginRootDirectory, this._oniPluginMetadata.main),\n        )\n        moduleEntryPoint = moduleEntryPoint.split(\"\\\\\").join(\"/\")\n\n        try {\n            vm.runInNewContext(\n                `debugger; const pluginEntryPoint = require('${moduleEntryPoint}').activate; if (!pluginEntryPoint) { console.warn('No activate method found for: ${moduleEntryPoint}'); } else { pluginContainer._instance = pluginEntryPoint(Oni); } `,\n                {\n                    pluginContainer: this,\n                    Oni: this._oni,\n                    require: window[\"require\"], // tslint:disable-line no-string-literal\n                    console,\n                },\n            )\n            Log.info(`[PLUGIN] Activation successful.`)\n        } catch (ex) {\n            Log.error(`[PLUGIN] Failed to load plugin: ${this._oniPluginMetadata.name}`, ex)\n            Log.error(ex)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/PluginConfigurationSynchronizer.ts",
    "content": "/**\n * PluginConfigurationSynchronizer.ts\n *\n * Responsible for synchronizing user's `plugin` configuration settings.\n */\n\nimport * as Log from \"oni-core-logging\"\n\nimport { Configuration } from \"./../Services/Configuration\"\nimport { PluginManager } from \"./PluginManager\"\n\nexport const activate = (configuration: Configuration, pluginManager: PluginManager): void => {\n    const setting = configuration.registerSetting<string[]>(\"plugins\", {\n        description:\n            \"`plugins` is an array of strings designating plugins that should be installed. Plugins can either be installed from `npm` (for Oni / JS plugins), or from GitHub (usually for Vim plugins). For an `npm` plugin, simply specify the package name - like 'oni-power-mode'. For a GitHub plugin, specify the user + plugin, for example 'tpope/vim-fugitive'\",\n        requiresReload: false,\n    })\n\n    setting.onValueChanged.subscribe(evt => {\n        if (!evt.newValue || !evt.newValue.length) {\n            return\n        }\n\n        Log.verbose(\"[PluginConfigurationSynchronizer - onValueChanged]\")\n\n        const newPlugins = evt.newValue.filter(plugin => evt.oldValue.indexOf(plugin) === -1)\n\n        Log.info(\"[PluginConfigurationSynchronizer] New Plugins: \" + newPlugins)\n\n        newPlugins.forEach(async plugin => {\n            Log.info(\"[PluginConfigurationSynchronizer] Installing plugin: \" + plugin)\n            await pluginManager.installer.install(plugin)\n            Log.info(\"[PluginConfigurationSynchronizer] Installation complete!\")\n        })\n    })\n}\n"
  },
  {
    "path": "browser/src/Plugins/PluginInstaller.ts",
    "content": "/**\n * PluginInstaller.ts\n *\n * Responsible for installing, updating, and uninstalling plugins.\n */\n\nimport * as path from \"path\"\n\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\n// import * as Oni from \"oni-api\"\n\nimport { getUserConfigFolderPath } from \"./../Services/Configuration\"\n// import { IContributions } from \"./Api/Capabilities\"\n\n// import { AnonymousPlugin } from \"./AnonymousPlugin\"\n// import { Plugin } from \"./Plugin\"\n\nimport { IFileSystem, OniFileSystem } from \"./../Services/Explorer/ExplorerFileSystem\"\n\nimport Process from \"./Api/Process\"\n\n/**\n * Plugin identifier:\n * - For _git_, this should be of the form `welle/targets.vim`\n * - For _npm_, this should be the name of the module, `oni-plugin-tslint`\n */\nexport type PluginIdentifier = string\n\nexport interface IPluginInstallerOperationEvent {\n    type: \"install\" | \"uninstall\"\n    identifier: string\n    error?: Error\n}\n\nexport interface IPluginInstaller {\n    onOperationStarted: IEvent<IPluginInstallerOperationEvent>\n    onOperationCompleted: IEvent<IPluginInstallerOperationEvent>\n    onOperationError: IEvent<IPluginInstallerOperationEvent>\n\n    install(pluginInfo: PluginIdentifier): Promise<void>\n    uninstall(pluginInfo: PluginIdentifier): Promise<void>\n}\n\nexport class YarnPluginInstaller implements IPluginInstaller {\n    private _onOperationStarted = new Event<IPluginInstallerOperationEvent>()\n    private _onOperationCompleted = new Event<IPluginInstallerOperationEvent>()\n    private _onOperationError = new Event<IPluginInstallerOperationEvent>()\n\n    public get onOperationStarted(): IEvent<IPluginInstallerOperationEvent> {\n        return this._onOperationStarted\n    }\n\n    public get onOperationCompleted(): IEvent<IPluginInstallerOperationEvent> {\n        return this._onOperationCompleted\n    }\n\n    public get onOperationError(): IEvent<IPluginInstallerOperationEvent> {\n        return this._onOperationError\n    }\n\n    constructor(private _fileSystem: IFileSystem = OniFileSystem) {}\n\n    public async install(identifier: string): Promise<void> {\n        const eventInfo: IPluginInstallerOperationEvent = {\n            type: \"install\",\n            identifier,\n        }\n\n        try {\n            this._onOperationStarted.dispatch(eventInfo)\n            await this._ensurePackageJsonIsCreated()\n            await this._runYarnCommand(\"add\", [identifier])\n            this._onOperationCompleted.dispatch(eventInfo)\n        } catch (ex) {\n            this._onOperationError.dispatch({\n                ...eventInfo,\n                error: ex,\n            })\n        }\n    }\n\n    public async uninstall(identifier: string): Promise<void> {\n        const eventInfo: IPluginInstallerOperationEvent = {\n            type: \"uninstall\",\n            identifier,\n        }\n\n        try {\n            this._onOperationStarted.dispatch(eventInfo)\n            await this._runYarnCommand(\"remove\", [identifier])\n            this._onOperationCompleted.dispatch(eventInfo)\n        } catch (ex) {\n            this._onOperationError.dispatch({\n                ...eventInfo,\n                error: ex,\n            })\n        }\n    }\n\n    private async _ensurePackageJsonIsCreated(): Promise<void> {\n        const packageJsonFile = this._getPackageJsonFile()\n        Log.info(\n            `[YarnPluginInstaller::_ensurePackageJsonIsCreated] - checking file: ${packageJsonFile}`,\n        )\n\n        const doesPackageFileExist = await this._fileSystem.exists(packageJsonFile)\n\n        if (!doesPackageFileExist) {\n            Log.info(\n                `[YarnPluginInstaller::_ensurePackageJsonIsCreated] - package file does not exist, initializing.`,\n            )\n            await this._runYarnCommand(\"init\", [\"-y\"])\n            Log.info(\n                `[YarnPluginInstaller::_ensurePackageJsonIsCreated] - package file created successfully.`,\n            )\n        } else {\n            Log.info(\n                `[YarnPluginInstaller::_ensurePackageJsonIsCreated] - package file is available.`,\n            )\n        }\n    }\n\n    private async _runYarnCommand(command: string, args: string[]): Promise<void> {\n        const yarnPath = this._getYarnPath()\n\n        const workingDirectory = getUserConfigFolderPath()\n        const pluginDirectory = this._getPluginsFolder()\n\n        return new Promise<void>((resolve, reject) => {\n            Process.execNodeScript(\n                yarnPath,\n                [\"--modules-folder\", pluginDirectory, \"--production\", \"true\", command, ...args],\n                { cwd: workingDirectory },\n                (err: any, stdout: string, stderr: string) => {\n                    if (err) {\n                        Log.error(\"Error installing: \" + stderr)\n                        reject(err)\n                        return\n                    }\n\n                    resolve()\n                },\n            )\n        })\n    }\n\n    private _getPackageJsonFile(): string {\n        return path.join(getUserConfigFolderPath(), \"package.json\")\n    }\n\n    private _getPluginsFolder(): string {\n        return path.join(getUserConfigFolderPath(), \"plugins\")\n    }\n\n    private _getYarnPath(): string {\n        return path.join(__dirname, \"lib\", \"yarn\", \"yarn-1.5.1.js\")\n    }\n}\n"
  },
  {
    "path": "browser/src/Plugins/PluginManager.ts",
    "content": "import * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { Configuration, getUserConfigFolderPath } from \"./../Services/Configuration\"\nimport { IContributions } from \"./Api/Capabilities\"\n\nimport { AnonymousPlugin } from \"./AnonymousPlugin\"\nimport { Plugin } from \"./Plugin\"\n\nconst corePluginsRoot = path.join(__dirname, \"vim\", \"core\")\nconst defaultPluginsRoot = path.join(__dirname, \"vim\", \"default\")\nconst extensionsRoot = path.join(__dirname, \"extensions\")\n\nimport { flatMap } from \"./../Utility\"\n\nimport { IPluginInstaller, YarnPluginInstaller } from \"./PluginInstaller\"\n\nexport class PluginManager implements Oni.IPluginManager {\n    private _rootPluginPaths: string[] = []\n    private _plugins: Plugin[] = []\n    private _anonymousPlugin: AnonymousPlugin\n    private _pluginsActivated: boolean = false\n    private _installer: IPluginInstaller = new YarnPluginInstaller()\n    private _pluginsLoaded = new Event<void>()\n\n    public get pluginsAllLoaded(): IEvent<void> {\n        return this._pluginsLoaded\n    }\n\n    private _developmentPluginsPath: string[] = []\n\n    public get plugins(): Plugin[] {\n        return this._plugins\n    }\n\n    public get installer(): IPluginInstaller {\n        return this._installer\n    }\n\n    constructor(private _config: Configuration) {}\n\n    public addDevelopmentPlugin(pluginPath: string): void {\n        this._developmentPluginsPath.push(pluginPath)\n    }\n\n    public discoverPlugins(): void {\n        const corePluginRootPaths: string[] = [corePluginsRoot, extensionsRoot]\n        const corePlugins: Plugin[] = this._getAllPluginPaths(corePluginRootPaths).map(p =>\n            this._createPlugin(p, \"core\"),\n        )\n\n        let defaultPluginRootPaths: string[] = []\n        let defaultPlugins: Plugin[] = []\n        if (this._config.getValue(\"oni.useDefaultConfig\")) {\n            defaultPluginRootPaths = [defaultPluginsRoot, path.join(defaultPluginsRoot, \"bundle\")]\n\n            defaultPlugins = this._getAllPluginPaths(defaultPluginRootPaths).map(p =>\n                this._createPlugin(p, \"default\"),\n            )\n        }\n\n        const userPluginsRootPath = [path.join(getUserConfigFolderPath(), \"plugins\")]\n        const userPlugins = this._getAllPluginPaths(userPluginsRootPath).map(p =>\n            this._createPlugin(p, \"user\"),\n        )\n\n        const developmentPlugins = this._developmentPluginsPath.map(dev =>\n            this._createPlugin(dev, \"development\"),\n        )\n\n        this._rootPluginPaths = [\n            ...corePluginRootPaths,\n            ...defaultPluginRootPaths,\n            ...userPluginsRootPath,\n        ]\n        this._plugins = [...corePlugins, ...defaultPlugins, ...userPlugins, ...developmentPlugins]\n\n        this._anonymousPlugin = new AnonymousPlugin()\n    }\n\n    public startApi(): Oni.Plugin.Api {\n        this._plugins.forEach(plugin => {\n            plugin.activate()\n        })\n\n        this._pluginsActivated = true\n        this._pluginsLoaded.dispatch()\n\n        return this.getApi()\n    }\n\n    public getApi(): Oni.Plugin.Api {\n        return this._anonymousPlugin.oni\n    }\n\n    public getAllRuntimePaths(): string[] {\n        const pluginPaths = [\n            ...this._getAllPluginPaths(this._rootPluginPaths),\n            ...this._developmentPluginsPath,\n        ]\n\n        return pluginPaths.concat(this._rootPluginPaths)\n    }\n\n    public get loaded(): boolean {\n        return this._pluginsActivated\n    }\n\n    public getPlugin(name: string): any {\n        for (const plugin of this._plugins) {\n            if (plugin.name === name) {\n                return plugin.instance\n            }\n        }\n        return null\n    }\n\n    public getAllContributionsOfType<T>(selector: (capabilities: IContributions) => T[]): T[] {\n        const filteredPlugins = this.plugins.filter(p => p.metadata && p.metadata.contributes)\n        const capabilities = flatMap(\n            filteredPlugins,\n            p => selector(p.metadata.contributes) || ([] as T[]),\n        )\n        return capabilities\n    }\n\n    private _createPlugin(pluginRootDirectory: string, source: string): Plugin {\n        return new Plugin(pluginRootDirectory, source)\n    }\n\n    private _getAllPluginPaths(rootPluginPaths: string[]): string[] {\n        const paths: string[] = []\n        rootPluginPaths.forEach(rp => {\n            const subPaths = getDirectories(rp)\n            paths.push(...subPaths)\n        })\n\n        return paths\n    }\n}\n\nlet _pluginManager: PluginManager = null\n\nexport const activate = (configuration: Configuration): void => {\n    _pluginManager = new PluginManager(configuration)\n}\n\nexport const getInstance = (): PluginManager => _pluginManager\n\nfunction getDirectories(rootPath: string): string[] {\n    if (!fs.existsSync(rootPath)) {\n        return []\n    }\n\n    return fs\n        .readdirSync(rootPath)\n        .map(f => path.join(rootPath.toString(), f))\n        .filter(f => fs.statSync(f).isDirectory())\n}\n"
  },
  {
    "path": "browser/src/Plugins/PluginSidebarPane.tsx",
    "content": "/**\n * PluginsSidebarPane.tsx\n *\n * Sidebar pane for managing plugins\n */\n\nimport * as React from \"react\"\n\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { CommandManager } from \"./../Services/CommandManager\"\nimport { Configuration } from \"./../Services/Configuration\"\nimport { SidebarManager, SidebarPane } from \"./../Services/Sidebar\"\n\nimport { SidebarContainerView, SidebarItemView } from \"./../UI/components/SidebarItemView\"\nimport { VimNavigator } from \"./../UI/components/VimNavigator\"\n\nimport { PluginManager } from \"./../Plugins/PluginManager\"\n\nimport { noop } from \"./../Utility\"\n\nimport * as Common from \"./../UI/components/common\"\n\nimport styled from \"styled-components\"\n\nconst PluginIconWrapper = styled.div`\n    background-color: rgba(0, 0, 0, 0.1);\n    width: 36px;\n    height: 36px;\n`\n\nconst PluginCommandsWrapper = styled.div`\n    flex: 0 0 auto;\n`\n\nconst PluginInfoWrapper = styled.div`\n    flex: 1 1 auto;\n    width: 100%;\n    justify-content: center;\n    display: flex;\n    flex-direction: column;\n    margin-left: 8px;\n    margin-right: 8px;\n`\n\nconst PluginTitleWrapper = styled.div`\n    font-size: 1.1em;\n`\n\nexport interface PluginSidebarItemViewProps {\n    name: string\n}\n\nexport class PluginSidebarItemView extends React.PureComponent<PluginSidebarItemViewProps, {}> {\n    public render(): JSX.Element {\n        return (\n            <Common.Container direction={\"horizontal\"} fullWidth={true}>\n                <Common.Fixed style={{ width: \"40px\", height: \"40px\" }}>\n                    <Common.Center>\n                        <PluginIconWrapper />\n                    </Common.Center>\n                </Common.Fixed>\n                <PluginInfoWrapper>\n                    <PluginTitleWrapper>{this.props.name}</PluginTitleWrapper>\n                </PluginInfoWrapper>\n                <PluginCommandsWrapper />\n            </Common.Container>\n        )\n    }\n}\n\nexport class PluginsSidebarPane implements SidebarPane {\n    private _onEnter = new Event<void>()\n    private _onLeave = new Event<void>()\n\n    public get id(): string {\n        return \"oni.sidebar.plugins\"\n    }\n\n    public get title(): string {\n        return \"Plugins\"\n    }\n\n    constructor(private _pluginManager: PluginManager) {}\n\n    public enter(): void {\n        this._onEnter.dispatch()\n    }\n\n    public leave(): void {\n        this._onLeave.dispatch()\n    }\n\n    public render(): JSX.Element {\n        return (\n            <PluginsSidebarPaneView\n                onEnter={this._onEnter}\n                onLeave={this._onLeave}\n                pluginManager={this._pluginManager}\n            />\n        )\n    }\n}\n\nexport interface IPluginsSidebarPaneViewProps {\n    onEnter: IEvent<void>\n    onLeave: IEvent<void>\n\n    pluginManager: PluginManager\n}\n\nexport interface IPluginsSidebarPaneViewState {\n    isActive: boolean\n    defaultPluginsExpanded: boolean\n    userPluginsExpanded: boolean\n    workspacePluginsExpanded: boolean\n}\n\nexport class PluginsSidebarPaneView extends React.PureComponent<\n    IPluginsSidebarPaneViewProps,\n    IPluginsSidebarPaneViewState\n> {\n    private _subscriptions: IDisposable[] = []\n\n    constructor(props: IPluginsSidebarPaneViewProps) {\n        super(props)\n\n        this.state = {\n            isActive: false,\n            defaultPluginsExpanded: false,\n            userPluginsExpanded: true,\n            workspacePluginsExpanded: false,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._clearExistingSubscriptions()\n\n        const s2 = this.props.onEnter.subscribe(() => this.setState({ isActive: true }))\n        const s3 = this.props.onLeave.subscribe(() => this.setState({ isActive: false }))\n\n        this._subscriptions = [s2, s3]\n    }\n\n    public componentWillUnmount(): void {\n        this._clearExistingSubscriptions()\n    }\n\n    public render(): JSX.Element {\n        const plugins = this.props.pluginManager.plugins\n\n        const defaultPlugins = plugins.filter(p => p.source === \"default\")\n        const userPlugins = plugins.filter(p => p.source === \"user\")\n\n        const defaultPluginIds = this.state.defaultPluginsExpanded\n            ? defaultPlugins.map(p => p.id)\n            : []\n        const userPluginIds = this.state.userPluginsExpanded ? userPlugins.map(p => p.id) : []\n\n        const allIds = [\n            \"container.default\",\n            ...defaultPluginIds,\n            \"container.workspace\",\n            \"container.user\",\n            ...userPluginIds,\n        ]\n\n        return (\n            <VimNavigator\n                ids={allIds}\n                active={this.state.isActive}\n                onSelected={id => this._onSelect(id)}\n                render={(selectedId: string) => {\n                    const defaultPluginItems = defaultPlugins.map(p => (\n                        <SidebarItemView\n                            key={p.id}\n                            indentationLevel={0}\n                            isFocused={p.id === selectedId}\n                            isContainer={false}\n                            text={<PluginSidebarItemView name={p.name || p.id} />}\n                            onClick={noop}\n                        />\n                    ))\n\n                    const userPluginItems = userPlugins.map(p => (\n                        <SidebarItemView\n                            key={p.id}\n                            indentationLevel={0}\n                            isFocused={p.id === selectedId}\n                            isContainer={false}\n                            text={<PluginSidebarItemView name={p.name || p.id} />}\n                            onClick={noop}\n                        />\n                    ))\n\n                    return (\n                        <div>\n                            <SidebarContainerView\n                                text={\"Bundled\"}\n                                isContainer={true}\n                                isExpanded={this.state.defaultPluginsExpanded}\n                                isFocused={selectedId === \"container.default\"}\n                                onClick={() => this._onSelect(\"container.default\")}\n                            >\n                                {defaultPluginItems}\n                            </SidebarContainerView>\n                            <SidebarContainerView\n                                text={\"Workspace\"}\n                                isContainer={true}\n                                isExpanded={this.state.workspacePluginsExpanded}\n                                isFocused={selectedId === \"container.workspace\"}\n                                onClick={() => this._onSelect(\"container.workspace\")}\n                            >\n                                {[]}\n                            </SidebarContainerView>\n                            <SidebarContainerView\n                                text={\"User\"}\n                                isContainer={true}\n                                isExpanded={this.state.userPluginsExpanded}\n                                isFocused={selectedId === \"container.user\"}\n                                onClick={() => this._onSelect(\"container.user\")}\n                            >\n                                {userPluginItems}\n                            </SidebarContainerView>\n                        </div>\n                    )\n                }}\n            />\n        )\n    }\n\n    private _onSelect(id: string): void {\n        switch (id) {\n            case \"container.default\":\n                this._toggleDefaultPluginsExpanded()\n                return\n            case \"container.user\":\n                this._toggleUserPluginsExpanded()\n                return\n        }\n    }\n\n    private _toggleDefaultPluginsExpanded(): void {\n        this.setState({\n            defaultPluginsExpanded: !this.state.defaultPluginsExpanded,\n        })\n    }\n\n    private _toggleUserPluginsExpanded(): void {\n        this.setState({\n            userPluginsExpanded: !this.state.userPluginsExpanded,\n        })\n    }\n\n    private _clearExistingSubscriptions(): void {\n        this._subscriptions.forEach(sub => sub.dispose())\n        this._subscriptions = []\n    }\n}\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    pluginManager: PluginManager,\n    sidebarManager: SidebarManager,\n) => {\n    if (configuration.getValue(\"sidebar.plugins.enabled\")) {\n        const pane = new PluginsSidebarPane(pluginManager)\n        sidebarManager.add(\"plug\", pane)\n    }\n\n    const togglePlugins = () => {\n        sidebarManager.toggleVisibilityById(\"oni.sidebar.plugins\")\n    }\n\n    commandManager.registerCommand({\n        command: \"plugins.toggle\",\n        name: \"Plugins: Toggle Visibility\",\n        detail: \"Toggles the plugins pane in the sidebar\",\n        execute: togglePlugins,\n        enabled: () => configuration.getValue(\"sidebar.plugins.enabled\"),\n    })\n}\n"
  },
  {
    "path": "browser/src/Redux/LoggingMiddleware.ts",
    "content": "/*\n * LoggingMiddleware\n *\n * Logging strategy for Redux, specific to Oni\n */\n\nimport { Store } from \"redux\"\n\nimport * as Log from \"oni-core-logging\"\n\nexport const createLoggingMiddleware = (storeName: string) => (store: Store<any>) => (\n    next: any,\n) => (action: any): any => {\n    Log.verbose(\"[REDUX - \" + storeName + \"][ACTION] \" + action.type)\n\n    const result = next(action)\n\n    return result\n}\n"
  },
  {
    "path": "browser/src/Redux/RequestAnimationFrameNotifyBatcher.ts",
    "content": "/*\n * RAFNotifyBatcher\n *\n * Helper method to 'batch' dispatches to redux store\n * subscriptions, based on animation frames.\n *\n * This helps 'debounce' the rendering logic -\n * otherwise we'd be re-rendering the UI every time\n * an action is dispatched.\n */\n\nimport { NotifyFunction } from \"redux-batched-subscribe\"\n\nexport const RequestAnimationFrameNotifyBatcher = () => {\n    let rafId: number = null\n\n    return (notify: NotifyFunction) => {\n        if (rafId) {\n            return\n        }\n\n        rafId = window.requestAnimationFrame(() => {\n            rafId = null\n            notify()\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Redux/createStore.ts",
    "content": "/*\n * createStore\n *\n * Common utilities for creating a redux store with Oni\n *\n * Implementations some common functionality, like:\n * - Logging\n * - Throttled subscriptions\n */\n\nimport {\n    applyMiddleware,\n    compose,\n    createStore as reduxCreateStore,\n    Middleware,\n    Reducer,\n    Store,\n} from \"redux\"\nimport { batchedSubscribe } from \"redux-batched-subscribe\"\n\nimport { createLoggingMiddleware } from \"./LoggingMiddleware\"\n\nimport { RequestAnimationFrameNotifyBatcher } from \"./RequestAnimationFrameNotifyBatcher\"\n\nexport const createStore = <TState>(\n    name: string,\n    reducer: Reducer<TState>,\n    defaultState: TState,\n    optionalMiddleware: Middleware[] = [],\n): Store<TState> => {\n    // tslint:disable-next-line no-string-literal\n    const composeFunction: any = window[\"__REDUX_DEVTOOLS_EXTENSION_COMPOSE__\"]\n\n    const composeEnhancers =\n        typeof window === \"object\" && composeFunction ? composeFunction({ name }) : compose // tslint:disable-line no-string-literal\n\n    const loggingMiddleware: Middleware = createLoggingMiddleware(name)\n\n    const middleware = [loggingMiddleware, ...optionalMiddleware]\n\n    const enhancer = composeEnhancers(\n        applyMiddleware(...middleware),\n        batchedSubscribe(RequestAnimationFrameNotifyBatcher()),\n    )\n    return reduxCreateStore(reducer, defaultState, enhancer)\n}\n"
  },
  {
    "path": "browser/src/Redux/index.ts",
    "content": "export * from \"./createStore\"\n"
  },
  {
    "path": "browser/src/Renderer/CanvasRenderer.ts",
    "content": "import { Grid } from \"./../Grid\"\nimport { ICell, MinimalScreenForRendering } from \"./../neovim\"\nimport * as Performance from \"./../Performance\"\nimport { INeovimRenderer } from \"./INeovimRenderer\"\nimport { getSpansToEdit, IPosition, ISpan } from \"./Span\"\n\nimport { configuration } from \"./../Services/Configuration\"\n\nexport interface IRenderState {\n    isWhitespace: boolean\n    foregroundColor: string\n    backgroundColor: string\n    text: string\n    startX: number\n    bold: boolean\n    italic: boolean\n    underline: boolean\n    y: number\n    width: number\n}\n\nconst isWhiteSpace = (text: string) => text === null || text === \"\" || text === \" \"\n\nconst cellsAreSameColor = (cell1: ICell, cell2: ICell): boolean => {\n    if (!cell1 || !cell2) {\n        return false\n    }\n\n    return (\n        cell1.backgroundColor === cell2.backgroundColor &&\n        cell1.foregroundColor === cell2.foregroundColor &&\n        cell1.characterWidth === 1 &&\n        cell2.characterWidth === 1\n    )\n}\n\nconst cellsAreEqual = (cell1: ICell, cell2: ICell): boolean => {\n    if (cell1 === cell2) {\n        return true\n    }\n\n    if (cellsAreSameColor(cell1, cell2) && cell1.character === cell2.character) {\n        return true\n    }\n\n    return false\n}\n\nexport class CanvasRenderer implements INeovimRenderer {\n    private _editorElement: HTMLDivElement\n    private _canvasElement: HTMLCanvasElement\n    private _canvasContext: CanvasRenderingContext2D\n\n    private _width: number\n    private _height: number\n\n    private _isOpaque: boolean\n\n    private _lastRenderGrid: Grid<ICell> = new Grid<ICell>()\n    private _grid: Grid<ISpan> = new Grid<ISpan>()\n    private _devicePixelRatio: number\n\n    public start(element: HTMLDivElement): void {\n        this._editorElement = element\n\n        this._setContext()\n    }\n\n    public onAction(_action: any): void {\n        // In the future, something like scrolling could be potentially optimized here\n    }\n\n    public redrawAll(screenInfo: MinimalScreenForRendering): void {\n        if (!this._editorElement) {\n            return\n        }\n\n        const cellsToUpdate: IPosition[] = []\n\n        this._setContext()\n\n        if (this._isOpaque) {\n            this._canvasContext.fillStyle = screenInfo.backgroundColor\n            this._canvasContext.fillRect(0, 0, this._width, this._height)\n        } else {\n            this._canvasContext.clearRect(0, 0, this._width, this._height)\n        }\n\n        this._lastRenderGrid.clear()\n\n        for (let x = 0; x < screenInfo.width; x++) {\n            for (let y = 0; y < screenInfo.height; y++) {\n                const cell = screenInfo.getCell(x, y)\n                cellsToUpdate.push({ x, y })\n                this._lastRenderGrid.setCell(x, y, cell)\n            }\n        }\n\n        this._draw(screenInfo, cellsToUpdate)\n    }\n\n    public draw(screenInfo: MinimalScreenForRendering): void {\n        if (!this._editorElement) {\n            return\n        }\n\n        const cellsToUpdate: IPosition[] = []\n        for (let x = 0; x < screenInfo.width; x++) {\n            for (let y = 0; y < screenInfo.height; y++) {\n                const lastCell = this._lastRenderGrid.getCell(x, y)\n                const currentCell = screenInfo.getCell(x, y)\n\n                if (!cellsAreEqual(lastCell, currentCell)) {\n                    cellsToUpdate.push({ x, y })\n                    this._lastRenderGrid.setCell(x, y, currentCell)\n                }\n            }\n        }\n\n        this._draw(screenInfo, cellsToUpdate)\n    }\n\n    public _draw(screenInfo: MinimalScreenForRendering, modifiedCells: IPosition[]): void {\n        Performance.mark(\"CanvasRenderer.update.start\")\n\n        this._canvasContext.font = `${screenInfo.fontWeight} ${screenInfo.fontSize} ${\n            screenInfo.fontFamily\n        }`\n        this._canvasContext.textBaseline = \"top\"\n        this._canvasContext.setTransform(this._devicePixelRatio, 0, 0, this._devicePixelRatio, 0, 0)\n        this._canvasContext.imageSmoothingEnabled = false\n\n        this._editorElement.style.fontFamily = screenInfo.fontFamily\n        this._editorElement.style.fontSize = screenInfo.fontSize\n        this._editorElement.style.fontWeight = screenInfo.fontWeight\n\n        const rowsToEdit = getSpansToEdit(this._grid, modifiedCells)\n\n        for (const y of Object.keys(rowsToEdit)) {\n            const row: ISpan[] = rowsToEdit[y]\n\n            if (!row) {\n                return\n            }\n\n            row.forEach((span: ISpan) => {\n                // All spans that have changed in current rendering pass\n\n                const rowIndex = Number.parseInt(y, 10)\n\n                const currentCell = screenInfo.getCell(span.startX, rowIndex)\n\n                // Check spans before & after, to see if they can be merged\n                // (In other words, if they should be re-rendered together)\n                // This is important for ligature cases.\n                const gridCellBefore = screenInfo.getCell(span.startX - 1, rowIndex)\n                const gridCellAfter = screenInfo.getCell(span.endX + 1, rowIndex)\n\n                let updatedStartX = span.startX\n                let updatedEndX = span.endX\n\n                if (cellsAreSameColor(currentCell, gridCellBefore)) {\n                    const previousCell = this._grid.getCell(span.startX - 1, rowIndex)\n                    if (previousCell) {\n                        updatedStartX = previousCell.startX\n                    }\n                }\n\n                if (cellsAreSameColor(currentCell, gridCellAfter)) {\n                    const afterCell = this._grid.getCell(span.endX + 1, rowIndex)\n\n                    if (afterCell) {\n                        updatedEndX = afterCell.endX\n                    }\n                }\n\n                const updatedSpan: ISpan = {\n                    startX: updatedStartX,\n                    endX: updatedEndX,\n                }\n\n                this._renderSpan(updatedSpan, rowIndex, screenInfo)\n            })\n        }\n\n        Performance.mark(\"CanvasRenderer.update.end\")\n    }\n\n    private _renderSpan(span: ISpan, y: number, screenInfo: MinimalScreenForRendering): void {\n        let prevState: IRenderState = {\n            isWhitespace: false,\n            foregroundColor: screenInfo.foregroundColor,\n            backgroundColor: screenInfo.backgroundColor,\n            text: \"\",\n            bold: false,\n            italic: false,\n            underline: false,\n            startX: span.startX,\n            y,\n            width: 0,\n        }\n\n        let x = span.startX\n        while (x < span.endX) {\n            const cell = screenInfo.getCell(x, y)\n\n            const nextRenderState = this._getNextRenderState(cell, x, y, prevState)\n\n            if (this._isNewState(prevState, nextRenderState)) {\n                this._renderText(prevState, screenInfo)\n            }\n\n            prevState = nextRenderState\n\n            const increment = nextRenderState.startX + nextRenderState.width\n            x = increment\n        }\n\n        this._renderText(prevState, screenInfo)\n    }\n\n    private _getNextRenderState(\n        cell: ICell,\n        x: number,\n        y: number,\n        currentState: IRenderState,\n    ): IRenderState {\n        const isCurrentCellWhiteSpace = isWhiteSpace(cell.character)\n        if (\n            cell.foregroundColor !== currentState.foregroundColor ||\n            cell.backgroundColor !== currentState.backgroundColor ||\n            isCurrentCellWhiteSpace !== currentState.isWhitespace ||\n            cell.characterWidth > 1\n        ) {\n            return {\n                isWhitespace: isCurrentCellWhiteSpace,\n                foregroundColor: cell.foregroundColor,\n                backgroundColor: cell.backgroundColor,\n                text: cell.character,\n                bold: cell.bold,\n                italic: cell.italic,\n                underline: cell.underline,\n                width: cell.characterWidth,\n                startX: x,\n                y,\n            }\n        } else {\n            const adjustedCharacterWidth = isCurrentCellWhiteSpace ? 1 : cell.characterWidth\n\n            // Not using spread (...) operator, which would simplify this,\n            // because this is a hot-path for rendering and `Object.assign`\n            // has some overhead that showed up in the profile.\n            return {\n                isWhitespace: currentState.isWhitespace,\n                foregroundColor: cell.foregroundColor,\n                backgroundColor: cell.backgroundColor,\n                text: currentState.text + cell.character,\n                bold: cell.bold,\n                italic: cell.italic,\n                underline: cell.underline,\n                width: currentState.width + adjustedCharacterWidth,\n                startX: currentState.startX,\n                y: currentState.y,\n            }\n        }\n    }\n\n    private _isNewState(oldState: IRenderState, newState: IRenderState) {\n        return oldState.startX !== newState.startX\n    }\n\n    private _renderText(state: IRenderState, screenInfo: MinimalScreenForRendering): void {\n        // Spans can have a width of 0 if they are placeholders for cells\n        // after a multibyte character. In this case, we don't need to bother\n        // rendering or clearing, because that occurs with the multibyte character.\n        if (state.width === 0) {\n            return\n        }\n\n        const { backgroundColor, foregroundColor, bold, italic, text, startX, y } = state\n\n        const { fontWidthInPixels, fontHeightInPixels, linePaddingInPixels } = screenInfo\n\n        const boundsStartX = startX * fontWidthInPixels\n        const boundsY = y * fontHeightInPixels\n        const boundsWidth = state.width * fontWidthInPixels\n\n        // This normalization is required to fix \"cracks\" due to anti-aliasing and rendering\n        // rectangles on subpixel boundaries. Sometimes, the rectangle will not \"connect\"\n        // between adjacent boundaries, and there is a crack between the blocks. Worse,\n        // sometimes when clearing a rectangle, a thin line will be left.\n        //\n        // This normalization addresses it by making sure the rectangle bounds are aligned\n        // to the nearest integer pixel.\n        const normalizedBoundsStartX = Math.floor(boundsStartX)\n        const delta = boundsStartX - normalizedBoundsStartX\n        const normalizedBoundsWidth = Math.ceil(boundsWidth + delta)\n\n        const normalizedBoundsY = Math.floor(boundsY)\n        const deltaY = boundsY - normalizedBoundsY\n        const normalizedHeight = Math.ceil(boundsY + deltaY)\n\n        this._canvasContext.fillStyle = backgroundColor || screenInfo.backgroundColor\n\n        if (this._isOpaque || (backgroundColor && backgroundColor !== screenInfo.backgroundColor)) {\n            this._canvasContext.fillRect(\n                normalizedBoundsStartX,\n                normalizedHeight,\n                normalizedBoundsWidth,\n                fontHeightInPixels,\n            )\n        } else {\n            this._canvasContext.clearRect(\n                normalizedBoundsStartX,\n                normalizedHeight,\n                normalizedBoundsWidth,\n                fontHeightInPixels,\n            )\n        }\n\n        if (!state.isWhitespace) {\n            const lastFontStyle = this._canvasContext.font\n            this._canvasContext.fillStyle = foregroundColor\n            if (bold) {\n                this._canvasContext.font = `bold ${this._canvasContext.font}`\n            }\n            if (italic) {\n                this._canvasContext.font = `italic ${this._canvasContext.font}`\n            }\n            this._canvasContext.fillText(\n                text,\n                boundsStartX,\n                normalizedBoundsY + linePaddingInPixels / 2,\n            )\n            this._canvasContext.font = lastFontStyle\n        }\n\n        // Commit span dimensions to grid\n        const spanInfoToCommit: ISpan = {\n            startX: state.startX,\n            endX: state.startX + state.width,\n        }\n\n        for (let x = state.startX; x < state.startX + state.width; x++) {\n            this._grid.setCell(x, state.y, spanInfoToCommit)\n        }\n    }\n\n    private _setContext(): void {\n        this._editorElement.innerHTML = \"\"\n        this._devicePixelRatio = window.devicePixelRatio\n\n        // offsetWidth and offsetHeight always return an integer\n        const editorWidth = this._editorElement.offsetWidth\n        const editorHeight = this._editorElement.offsetHeight\n\n        this._canvasElement = document.createElement(\"canvas\")\n        this._canvasElement.style.width = editorWidth + \"px\"\n        this._canvasElement.style.height = editorHeight + \"px\"\n\n        this._editorElement.appendChild(this._canvasElement)\n\n        this._width = this._canvasElement.width = editorWidth * this._devicePixelRatio\n        this._height = this._canvasElement.height = editorHeight * this._devicePixelRatio\n\n        if (\n            configuration.getValue(\"editor.backgroundImageUrl\") &&\n            configuration.getValue(\"editor.backgroundOpacity\") < 1.0\n        ) {\n            this._canvasContext = this._canvasElement.getContext(\"2d\", { alpha: true })\n            this._isOpaque = false\n        } else {\n            this._canvasContext = this._canvasElement.getContext(\"2d\", { alpha: false })\n            this._isOpaque = true\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/INeovimRenderer.ts",
    "content": "import { IScreen } from \"./../neovim\"\n\nexport interface IPosition {\n    x: number\n    y: number\n}\n\nexport interface INeovimRenderer {\n    start(element: HTMLElement): void\n\n    redrawAll(screenInfo: IScreen): void\n\n    draw(screenInfo: IScreen): void\n\n    onAction(action: any): void\n}\n"
  },
  {
    "path": "browser/src/Renderer/Span.ts",
    "content": "import { Grid } from \"./../Grid\"\n\nexport interface ISpan {\n    startX: number\n    endX: number\n}\n\nexport interface IPosition {\n    x: number\n    y: number\n}\n\nexport interface RowMap {\n    [key: number]: ISpan[]\n}\n\nexport function getSpansToEdit(grid: Grid<ISpan>, cells: IPosition[]): RowMap {\n    const rowToSpans: RowMap = {}\n    cells.forEach(cell => {\n        const { x, y } = cell\n\n        const info = grid.getCell(x, y)\n        const currentRow = rowToSpans[y] || []\n\n        if (!info) {\n            currentRow.push({\n                startX: x,\n                endX: x + 1,\n            })\n        } else {\n            currentRow.push({\n                startX: info.startX,\n                endX: info.endX,\n            })\n\n            grid.setRegion(info.startX, y, info.endX - info.startX, 1, null)\n        }\n\n        rowToSpans[y] = currentRow\n    })\n    return collapseSpanMap(rowToSpans)\n}\n\nexport function collapseSpanMap(currentSpanMap: RowMap): RowMap {\n    const outMap = {}\n    for (const k of Object.keys(currentSpanMap)) {\n        outMap[k] = collapseSpans(currentSpanMap[k])\n    }\n\n    return outMap\n}\n\nexport function collapseSpans(spans: ISpan[] | undefined): ISpan[] {\n    if (!spans) {\n        return []\n    }\n\n    const flattenedArray = flattenSpansToArray(spans)\n    return expandArrayToSpans(flattenedArray)\n}\n\nexport function flattenSpansToArray(spans: ISpan[]): any[] {\n    if (!spans || !spans.length) {\n        return []\n    }\n\n    const bounds = spans.reduce(\n        (prev, cur) => ({\n            startX: Math.min(prev.startX, cur.startX),\n            endX: Math.max(prev.endX, cur.endX),\n        }),\n        { startX: spans[0].startX, endX: spans[0].endX },\n    )\n\n    const array: any[] = []\n\n    for (let x = 0; x < bounds.startX; x++) {\n        array.push(null)\n    }\n\n    for (let x = bounds.startX; x < bounds.endX; x++) {\n        array.push(false)\n    }\n\n    spans.forEach(s => {\n        for (let i = s.startX; i < s.endX; i++) {\n            array[i] = true\n        }\n    })\n\n    return array\n}\n\nexport function expandArrayToSpans(array: any[]): ISpan[] {\n    if (!array || !array.length) {\n        return []\n    }\n\n    let start = 0\n    while (array[start] === null) {\n        start++\n    }\n\n    const spans: ISpan[] = []\n    let currentSpan: ISpan | null = null\n\n    let x = 0\n    while (x < array.length) {\n        if (array[x]) {\n            if (currentSpan === null) {\n                currentSpan = {\n                    startX: x,\n                    endX: -1,\n                }\n            }\n        } else {\n            if (currentSpan !== null) {\n                currentSpan.endX = x\n                spans.push(currentSpan)\n                currentSpan = null\n            }\n        }\n\n        x++\n    }\n\n    if (currentSpan) {\n        currentSpan.endX = array.length\n        spans.push(currentSpan)\n    }\n\n    return spans\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/SolidRenderer.ts",
    "content": "import { ICell } from \"../../neovim\"\nimport { normalizeColor } from \"./normalizeColor\"\nimport {\n    createProgram,\n    createUnitQuadElementIndicesBuffer,\n    createUnitQuadVerticesBuffer,\n} from \"./WebGLUtilities\"\n\nconst solidInstanceFieldCount = 8\nconst solidInstanceSizeInBytes = solidInstanceFieldCount * Float32Array.BYTES_PER_ELEMENT\n\nconst vertexShaderAttributes = {\n    unitQuadVertex: 0,\n    targetOrigin: 1,\n    targetSize: 2,\n    colorRGBA: 3,\n}\n\nconst vertexShaderSource = `\n    #version 300 es\n\n    layout (location = 0) in vec2 unitQuadVertex;\n    layout (location = 1) in vec2 targetOrigin;\n    layout (location = 2) in vec2 targetSize;\n    layout (location = 3) in vec4 colorRGBA;\n    flat out vec4 color;\n\n    uniform vec2 viewportScale;\n\n    void main() {\n        vec2 targetPixelPosition = targetOrigin + unitQuadVertex * targetSize;\n        vec2 targetPosition = targetPixelPosition * viewportScale + vec2(-1.0, 1.0);\n        gl_Position = vec4(targetPosition, 0.0, 1.0);\n        color = colorRGBA;\n    }\n`.trim()\n\nconst fragmentShaderSource = `\n    #version 300 es\n\n    precision mediump float;\n\n    flat in vec4 color;\n    layout (location = 0) out vec4 outColor;\n\n    void main() {\n        outColor = color;\n    }\n`.trim()\n\nexport class SolidRenderer {\n    private _program: WebGLProgram\n    private _viewportScaleLocation: WebGLUniformLocation\n    private _unitQuadVerticesBuffer: WebGLBuffer\n    private _unitQuadElementIndicesBuffer: WebGLBuffer\n    private _solidInstances: Float32Array\n    private _solidInstancesBuffer: WebGLBuffer\n    private _vertexArrayObject: WebGLVertexArrayObject\n\n    constructor(private _gl: WebGL2RenderingContext, private _devicePixelRatio: number) {\n        this._program = createProgram(this._gl, vertexShaderSource, fragmentShaderSource)\n        this._viewportScaleLocation = this._gl.getUniformLocation(this._program, \"viewportScale\")\n\n        this._createBuffers()\n        this._createVertexArrayObject()\n    }\n\n    public draw(\n        columnCount: number,\n        rowCount: number,\n        getCell: (columnIndex: number, rowIndex: number) => ICell,\n        fontWidthInPixels: number,\n        fontHeightInPixels: number,\n        defaultBackgroundColor: string,\n        viewportScaleX: number,\n        viewportScaleY: number,\n    ) {\n        const cellCount = columnCount * rowCount\n        this._recreateSolidInstancesArrayIfRequired(cellCount)\n        const solidInstanceCount = this._populateSolidInstances(\n            columnCount,\n            rowCount,\n            getCell,\n            fontWidthInPixels,\n            fontHeightInPixels,\n            defaultBackgroundColor,\n        )\n        this._drawSolidInstances(solidInstanceCount, viewportScaleX, viewportScaleY)\n    }\n\n    private _createBuffers() {\n        this._unitQuadVerticesBuffer = createUnitQuadVerticesBuffer(this._gl)\n        this._unitQuadElementIndicesBuffer = createUnitQuadElementIndicesBuffer(this._gl)\n        this._solidInstancesBuffer = this._gl.createBuffer()\n    }\n\n    private _createVertexArrayObject() {\n        this._vertexArrayObject = this._gl.createVertexArray()\n        this._gl.bindVertexArray(this._vertexArrayObject)\n\n        this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, this._unitQuadElementIndicesBuffer)\n\n        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, this._unitQuadVerticesBuffer)\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.unitQuadVertex)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.unitQuadVertex,\n            2,\n            this._gl.FLOAT,\n            false,\n            0,\n            0,\n        )\n\n        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, this._solidInstancesBuffer)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.targetOrigin)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.targetOrigin,\n            2,\n            this._gl.FLOAT,\n            false,\n            solidInstanceSizeInBytes,\n            0,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.targetOrigin, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.targetSize)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.targetSize,\n            2,\n            this._gl.FLOAT,\n            false,\n            solidInstanceSizeInBytes,\n            2 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.targetSize, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.colorRGBA)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.colorRGBA,\n            4,\n            this._gl.FLOAT,\n            false,\n            solidInstanceSizeInBytes,\n            4 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.colorRGBA, 1)\n    }\n\n    private _recreateSolidInstancesArrayIfRequired(cellCount: number) {\n        const requiredArrayLength = cellCount * solidInstanceFieldCount\n        if (!this._solidInstances || this._solidInstances.length < requiredArrayLength) {\n            this._solidInstances = new Float32Array(requiredArrayLength)\n        }\n    }\n\n    private _populateSolidInstances(\n        columnCount: number,\n        rowCount: number,\n        getCell: (columnIndex: number, rowIndex: number) => ICell,\n        fontWidthInPixels: number,\n        fontHeightInPixels: number,\n        defaultBackgroundColor: string,\n    ) {\n        const pixelRatioAdaptedFontWidth = fontWidthInPixels * this._devicePixelRatio\n        const pixelRatioAdaptedFontHeight = fontHeightInPixels * this._devicePixelRatio\n\n        let solidCellCount = 0\n        let y = 0\n\n        for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n            let x = 0\n\n            for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {\n                const cell = getCell(columnIndex, rowIndex)\n\n                if (cell.backgroundColor && cell.backgroundColor !== defaultBackgroundColor) {\n                    const colorToUse = cell.backgroundColor || defaultBackgroundColor || \"black\"\n                    const normalizedBackgroundColor = normalizeColor(colorToUse)\n\n                    this._updateSolidInstance(\n                        solidCellCount,\n                        x,\n                        y,\n                        pixelRatioAdaptedFontWidth,\n                        pixelRatioAdaptedFontHeight,\n                        normalizedBackgroundColor,\n                    )\n\n                    solidCellCount++\n                }\n                x += pixelRatioAdaptedFontWidth\n            }\n\n            y += pixelRatioAdaptedFontHeight\n        }\n\n        return solidCellCount\n    }\n\n    private _drawSolidInstances(\n        solidCount: number,\n        viewportScaleX: number,\n        viewportScaleY: number,\n    ) {\n        this._gl.bindVertexArray(this._vertexArrayObject)\n        this._gl.disable(this._gl.BLEND)\n        this._gl.useProgram(this._program)\n        this._gl.uniform2f(this._viewportScaleLocation, viewportScaleX, viewportScaleY)\n        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, this._solidInstancesBuffer)\n        this._gl.bufferData(this._gl.ARRAY_BUFFER, this._solidInstances, this._gl.STREAM_DRAW)\n        this._gl.drawElementsInstanced(this._gl.TRIANGLES, 6, this._gl.UNSIGNED_BYTE, 0, solidCount)\n    }\n\n    private _updateSolidInstance(\n        index: number,\n        x: number,\n        y: number,\n        width: number,\n        height: number,\n        color: Float32Array,\n    ) {\n        const startOffset = solidInstanceFieldCount * index\n        // targetOrigin\n        this._solidInstances[0 + startOffset] = x\n        this._solidInstances[1 + startOffset] = y\n        // targetSize\n        this._solidInstances[2 + startOffset] = width\n        this._solidInstances[3 + startOffset] = height\n        // colorRGBA\n        this._solidInstances[4 + startOffset] = color[0]\n        this._solidInstances[5 + startOffset] = color[1]\n        this._solidInstances[6 + startOffset] = color[2]\n        this._solidInstances[7 + startOffset] = color[3]\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/GlyphAtlas/GlyphAtlas.ts",
    "content": "import { IRasterizedGlyph } from \"./IRasterizedGlyph\"\n\nconst backgroundColor = \"black\"\nconst foregroundColor = \"white\"\n\nexport interface IGlyphAtlasOptions {\n    fontFamily: string\n    fontSize: string\n    fontWeight: number | string\n    lineHeightInPixels: number\n    linePaddingInPixels: number\n    glyphPaddingInPixels: number\n    devicePixelRatio: number\n    offsetGlyphVariantCount: number\n    textureSizeInPixels: number\n    textureLayerCount: number\n}\n\nexport class WebGLTextureSpaceExceededError extends Error {}\n\nexport class GlyphAtlas {\n    private _rasterizingContext: CanvasRenderingContext2D\n    private _rasterizedGlyphs = new Map<string, IRasterizedGlyph>()\n    private _texture: WebGLTexture\n    private _currentTextureLayerIndex = 0\n    private _currentTextureLayerChangedSinceLastUpload = false\n    private _nextX = 0\n    private _nextY = 0\n\n    constructor(private _gl: WebGL2RenderingContext, private _options: IGlyphAtlasOptions) {\n        // TODO we should share at least the rasterizingCanvas and maybe even the texture among different buffers\n        const rasterizingCanvas = document.createElement(\"canvas\")\n        rasterizingCanvas.width = this._options.textureSizeInPixels\n        rasterizingCanvas.height = this._options.textureSizeInPixels\n        this._rasterizingContext = rasterizingCanvas.getContext(\"2d\", { alpha: false })\n        this._rasterizingContext.fillStyle = foregroundColor\n        this._rasterizingContext.textBaseline = \"top\"\n        this._rasterizingContext.scale(_options.devicePixelRatio, _options.devicePixelRatio)\n        this._rasterizingContext.imageSmoothingEnabled = false\n\n        document.body.appendChild(rasterizingCanvas)\n\n        this._texture = this._gl.createTexture()\n        this._gl.bindTexture(this._gl.TEXTURE_2D_ARRAY, this._texture)\n        this._gl.texParameteri(\n            this._gl.TEXTURE_2D_ARRAY,\n            this._gl.TEXTURE_MIN_FILTER,\n            this._gl.LINEAR,\n        )\n        this._gl.texParameteri(\n            this._gl.TEXTURE_2D_ARRAY,\n            this._gl.TEXTURE_WRAP_S,\n            this._gl.CLAMP_TO_EDGE,\n        )\n        this._gl.texParameteri(\n            this._gl.TEXTURE_2D_ARRAY,\n            this._gl.TEXTURE_WRAP_T,\n            this._gl.CLAMP_TO_EDGE,\n        )\n\n        const textureLayerCount = Math.min(\n            this._options.textureLayerCount,\n            this._gl.MAX_ARRAY_TEXTURE_LAYERS,\n        )\n        this._gl.texImage3D(\n            this._gl.TEXTURE_2D_ARRAY,\n            0,\n            this._gl.RGBA,\n            this._options.textureSizeInPixels,\n            this._options.textureSizeInPixels,\n            textureLayerCount,\n            0,\n            this._gl.RGBA,\n            this._gl.UNSIGNED_BYTE,\n            null,\n        )\n    }\n\n    public getRasterizedGlyph(\n        text: string,\n        isBold: boolean,\n        isItalic: boolean,\n        variantIndex: number,\n    ) {\n        const glyphKey = `${text} ${isBold ? \"b\" : \"\"}${isItalic ? \"i\" : \"\"}${variantIndex}`\n        let rasterizedGlyph = this._rasterizedGlyphs.get(glyphKey)\n        if (!rasterizedGlyph) {\n            rasterizedGlyph = this._rasterizeGlyph(text, isBold, isItalic, variantIndex)\n            this._rasterizedGlyphs.set(glyphKey, rasterizedGlyph)\n        }\n        return rasterizedGlyph\n    }\n\n    public uploadTexture() {\n        if (this._currentTextureLayerChangedSinceLastUpload) {\n            this._gl.bindTexture(this._gl.TEXTURE_2D_ARRAY, this._texture)\n            this._gl.texSubImage3D(\n                this._gl.TEXTURE_2D_ARRAY,\n                0,\n                0,\n                0,\n                this._currentTextureLayerIndex,\n                this._options.textureSizeInPixels,\n                this._options.textureSizeInPixels,\n                1,\n                this._gl.RGBA,\n                this._gl.UNSIGNED_BYTE,\n                this._rasterizingContext.canvas,\n            )\n            this._currentTextureLayerChangedSinceLastUpload = false\n        }\n    }\n\n    private _rasterizeGlyph(\n        text: string,\n        isBold: boolean,\n        isItalic: boolean,\n        variantIndex: number,\n    ) {\n        this._currentTextureLayerChangedSinceLastUpload = true\n\n        const {\n            fontWeight,\n            devicePixelRatio,\n            lineHeightInPixels,\n            linePaddingInPixels,\n            glyphPaddingInPixels,\n            offsetGlyphVariantCount,\n        } = this._options\n        const style = getGlyphStyleString(fontWeight, isBold, isItalic)\n        this._rasterizingContext.font = `${style} ${this._options.fontSize} ${\n            this._options.fontFamily\n        }`\n        const variantOffset = variantIndex / offsetGlyphVariantCount\n\n        const height = lineHeightInPixels + 2 * glyphPaddingInPixels\n        const { width: measuredGlyphWidth } = this._rasterizingContext.measureText(text)\n        const width =\n            Math.ceil(variantOffset) + Math.ceil(measuredGlyphWidth) + 2 * glyphPaddingInPixels\n\n        if ((this._nextX + width) * devicePixelRatio > this._options.textureSizeInPixels) {\n            this._nextX = 0\n            this._nextY = Math.ceil(this._nextY + height)\n        }\n\n        if ((this._nextY + height) * devicePixelRatio > this._options.textureSizeInPixels) {\n            this._switchToNextLayer()\n        }\n\n        const x = this._nextX\n        const y = this._nextY\n        this._rasterizingContext.fillText(\n            text,\n            x + glyphPaddingInPixels + variantOffset,\n            y + glyphPaddingInPixels + linePaddingInPixels / 2,\n        )\n        this._nextX += width\n\n        const rasterizedGlyph: IRasterizedGlyph = {\n            width: width * devicePixelRatio,\n            height: height * devicePixelRatio,\n            textureLayerIndex: this._currentTextureLayerIndex,\n            textureU: x * devicePixelRatio / this._options.textureSizeInPixels,\n            textureV: y * devicePixelRatio / this._options.textureSizeInPixels,\n            textureWidth: width * devicePixelRatio / this._options.textureSizeInPixels,\n            textureHeight: height * devicePixelRatio / this._options.textureSizeInPixels,\n            variantOffset,\n        }\n        return rasterizedGlyph\n    }\n\n    private _switchToNextLayer() {\n        if (this._currentTextureLayerIndex + 1 >= this._options.textureLayerCount) {\n            throw new WebGLTextureSpaceExceededError(\n                \"The WebGL renderer ran out of texture space. Please re-open the editor \" +\n                    \"with more texture layers or switch to a different renderer.\",\n            )\n        }\n\n        this.uploadTexture()\n\n        this._rasterizingContext.fillStyle = backgroundColor\n        this._rasterizingContext.fillRect(\n            0,\n            0,\n            this._rasterizingContext.canvas.width,\n            this._rasterizingContext.canvas.width,\n        )\n        this._rasterizingContext.fillStyle = foregroundColor\n        this._currentTextureLayerIndex++\n        this._nextX = 0\n        this._nextY = 0\n        this._currentTextureLayerChangedSinceLastUpload = true\n    }\n}\n\nconst defaultFontWeight = 400\n\nconst getGlyphStyleString = (\n    baseFontWeight: number | string = defaultFontWeight,\n    isBold: boolean,\n    isItalic: boolean,\n) => {\n    const fontWeight = isBold\n        ? getIncreasedFontWeightForBoldText(baseFontWeight)\n        : getNumericFontWeight(baseFontWeight) || defaultFontWeight\n    return \"\" + fontWeight + (isItalic ? \" italic\" : \"\")\n}\n\nconst addedFontWeightForBoldText = 300\nconst maxFontWeight = 900\n\nconst getIncreasedFontWeightForBoldText = (baseFontWeight: number | string) => {\n    const numericBaseFontWeight = getNumericFontWeight(baseFontWeight)\n    return Math.min(numericBaseFontWeight + addedFontWeightForBoldText, maxFontWeight)\n}\n\nconst getNumericFontWeight = (fontWeight: number | string) => {\n    if (typeof fontWeight === \"number\") {\n        return fontWeight\n    } else {\n        return numericFontWeightMap[fontWeight] || defaultFontWeight\n    }\n}\n\nconst numericFontWeightMap = {\n    normal: 400,\n    bold: 700,\n    // The following two should in fact be dynamic based on the weight of other elements\n    // but this is too complex and not relevant enough to warrant respecting this logic\n    bolder: 700,\n    lighter: 300,\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/GlyphAtlas/IRasterizedGlyph.ts",
    "content": "export interface IRasterizedGlyph {\n    width: number\n    height: number\n    textureLayerIndex: number\n    textureWidth: number\n    textureHeight: number\n    textureU: number\n    textureV: number\n    variantOffset: number\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/GlyphAtlas/index.ts",
    "content": "export * from \"./GlyphAtlas\"\nexport * from \"./IRasterizedGlyph\"\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/ICellGroup.ts",
    "content": "export interface ICellGroup {\n    startColumnIndex: number\n    characters: string[]\n    foregroundColor?: string\n    backgroundColor?: string\n    italic?: boolean\n    bold?: boolean\n    underline?: boolean\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/LigatureGrouper/ILigatureGrouper.ts",
    "content": "export interface ILigatureGrouper {\n    getLigatureGroups(characters: string[]): string[]\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/LigatureGrouper/NoopLigatureGrouper.ts",
    "content": "import { ILigatureGrouper } from \"./ILigatureGrouper\"\n\nexport class NoopLigatureGrouper implements ILigatureGrouper {\n    public getLigatureGroups(characters: string[]) {\n        return characters\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/LigatureGrouper/OpenTypeLigatureGrouper.ts",
    "content": "import fontManager from \"font-manager\"\nimport * as fs from \"fs\"\nimport * as Log from \"oni-core-logging\"\nimport oniFontkit, { Font } from \"oni-fontkit\"\n\nimport { ILigatureGrouper } from \"./ILigatureGrouper\"\n\nconst ligatureFeatures = [\"calt\", \"rclt\", \"liga\", \"dlig\", \"clig\"]\n\nexport class OpenTypeLigatureGrouper implements ILigatureGrouper {\n    private readonly _font = loadFont(this._fontFamily)\n    private readonly _fontHasLigatures = this._font && checkIfFontHasLigatures(this._font)\n    private readonly _cache = new Map<string, string[]>()\n\n    constructor(private _fontFamily: string) {}\n\n    public getLigatureGroups(characters: string[]) {\n        if (!this._fontHasLigatures) {\n            return characters\n        }\n\n        const concatenatedCharacters = characters.join(\"\")\n\n        const cachedLigatureGroups = this._cache.get(concatenatedCharacters)\n        if (cachedLigatureGroups) {\n            return cachedLigatureGroups\n        }\n\n        const fontGlyphs = this._font.glyphsForString(concatenatedCharacters)\n        // Apply ligatures and get the contextGroup metadata in the Glyphs where context-based replacements happened\n        const contextGroupArray = this._font.applySubstitutionFeatures(fontGlyphs, ligatureFeatures)\n        const ligatureGroups: string[] = []\n        let currentContextGroupId: number = null\n        contextGroupArray.forEach((contextGroupId, index) => {\n            if (contextGroupId !== currentContextGroupId) {\n                currentContextGroupId = contextGroupId\n                ligatureGroups.push(\"\")\n            }\n            ligatureGroups[ligatureGroups.length - 1] += concatenatedCharacters[index]\n        })\n\n        this._cache.set(concatenatedCharacters, ligatureGroups)\n        return [...ligatureGroups]\n    }\n}\n\nconst loadFont = (fontFamily: string) => {\n    try {\n        const fontDescriptor = findMatchingFont(fontFamily)\n        if (!fontDescriptor) {\n            Log.warn(\n                `[OpenTypeLigatureGrouper] Could not find installed font for font family '${fontFamily}'. Ligatures won't be available.`,\n            )\n            return null\n        }\n\n        const fontFileBuffer = fs.readFileSync(fontDescriptor.path)\n        const font = oniFontkit.create(fontFileBuffer)\n        Log.verbose(\n            `[OpenTypeLigatureGrouper] Using font ${fontDescriptor.postscriptName} located at ${\n                fontDescriptor.path\n            } for finding ligatures in '${fontFamily}'`,\n        )\n        return font\n    } catch (error) {\n        Log.warn(\n            `[OpenTypeLigatureGrouper] Error loading font file for font family '${fontFamily}': ${error} Ligatures won't be available.`,\n        )\n        return null\n    }\n}\n\n// This is a platform-independent reimplementation of the matching logic within font-manager's\n// findFont* methods.\n// We reimplemented it here because we encountered inconsistencies with matching on Windows.\nconst findMatchingFont = (fontFamily: string) => {\n    const availableFonts = fontManager.getAvailableFontsSync()\n    const fontWithMatchingFamily = availableFonts.find(font => font.family === fontFamily)\n    if (fontWithMatchingFamily) {\n        return fontWithMatchingFamily\n    } else {\n        // Chromium allows to use the postscript name of the font as well, so we do the same\n        // for compatibility\n        const fontWithMatchingPostscriptName = availableFonts.find(\n            font => font.postscriptName === fontFamily,\n        )\n        return fontWithMatchingPostscriptName\n    }\n}\n\nconst checkIfFontHasLigatures = (font: Font) => {\n    const fontHasLigatures = ligatureFeatures.some(\n        ligatureFeature =>\n            font && font.availableFeatures && font.availableFeatures.includes(ligatureFeature),\n    )\n    if (fontHasLigatures) {\n        Log.verbose(\n            `[OpenTypeLigatureGrouper] Found ligatures in '${\n                font.postscriptName\n            }'. Ligatures will be available.`,\n        )\n        return true\n    } else {\n        Log.verbose(\n            `[OpenTypeLigatureGrouper] Could not find ligatures in '${\n                font.postscriptName\n            }'. Ligatures won't be available.`,\n        )\n        return false\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/LigatureGrouper/index.ts",
    "content": "export * from \"./ILigatureGrouper\"\nexport * from \"./OpenTypeLigatureGrouper\"\nexport * from \"./NoopLigatureGrouper\"\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/TextRenderer.ts",
    "content": "import { ICell } from \"../../../neovim\"\nimport { normalizeColor } from \"../normalizeColor\"\nimport {\n    createProgram,\n    createUnitQuadElementIndicesBuffer,\n    createUnitQuadVerticesBuffer,\n} from \"../WebGLUtilities\"\nimport { GlyphAtlas, IGlyphAtlasOptions, IRasterizedGlyph } from \"./GlyphAtlas\"\nimport { groupCells } from \"./groupCells\"\nimport { ILigatureGrouper } from \"./LigatureGrouper\"\n\nconst glyphInstanceFieldCount = 13\nconst glyphInstanceSizeInBytes = glyphInstanceFieldCount * Float32Array.BYTES_PER_ELEMENT\n\nconst vertexShaderAttributes = {\n    unitQuadVertex: 0,\n    targetOrigin: 1,\n    targetSize: 2,\n    textColorRGBA: 3,\n    atlasLayerIndex: 4,\n    atlasOrigin: 5,\n    atlasSize: 6,\n}\n\nconst vertexShaderSource = `\n    #version 300 es\n\n    layout (location = 0) in vec2 unitQuadVertex;\n    layout (location = 1) in vec2 targetOrigin;\n    layout (location = 2) in vec2 targetSize;\n    layout (location = 3) in vec4 textColorRGBA;\n    layout (location = 4) in float atlasLayerIndex;\n    layout (location = 5) in vec2 atlasOrigin;\n    layout (location = 6) in vec2 atlasSize;\n\n    uniform vec2 viewportScale;\n\n    flat out vec4 textColor;\n    flat out int convertedAtlasLayerIndex;\n    out vec2 atlasPosition;\n\n    void main() {\n        vec2 targetPixelPosition = targetOrigin + unitQuadVertex * targetSize;\n        vec2 targetPosition = targetPixelPosition * viewportScale + vec2(-1.0, 1.0);\n        gl_Position = vec4(targetPosition, 0.0, 1.0);\n        textColor = textColorRGBA;\n        convertedAtlasLayerIndex = int(atlasLayerIndex);\n        atlasPosition = atlasOrigin + unitQuadVertex * atlasSize;\n    }\n`.trim()\n\nconst firstPassFragmentShaderSource = `\n    #version 300 es\n\n    precision mediump float;\n    precision mediump sampler2DArray;\n\n    layout(location = 0) out vec4 outColor;\n    flat in vec4 textColor;\n    flat in int convertedAtlasLayerIndex;\n    in vec2 atlasPosition;\n\n    uniform sampler2DArray atlasTextures;\n\n    void main() {\n      vec4 atlasColor = texture(atlasTextures, vec3(atlasPosition, convertedAtlasLayerIndex));\n      outColor = textColor.a * atlasColor;\n    }\n`.trim()\n\nconst secondPassFragmentShaderSource = `\n    #version 300 es\n\n    precision mediump float;\n    precision mediump sampler2DArray;\n\n    layout(location = 0) out vec4 outColor;\n    flat in vec4 textColor;\n    flat in int convertedAtlasLayerIndex;\n    in vec2 atlasPosition;\n\n    uniform sampler2DArray atlasTextures;\n\n    void main() {\n        vec3 atlasColor = texture(atlasTextures, vec3(atlasPosition, convertedAtlasLayerIndex)).rgb;\n        vec3 outColorRGB = atlasColor * textColor.rgb;\n        float outColorA = max(outColorRGB.r, max(outColorRGB.g, outColorRGB.b));\n        outColor = vec4(outColorRGB, outColorA);\n    }\n`.trim()\n\nexport class TextRenderer {\n    private _atlas: GlyphAtlas\n    private _glyphOverlapInPixels: number\n    private _subpixelDivisor: number\n    private _devicePixelRatio: number\n\n    private _firstPassProgram: WebGLProgram\n    private _firstPassViewportScaleLocation: WebGLUniformLocation\n    private _firstPassAtlasTexturesLocation: WebGLUniformLocation\n    private _secondPassProgram: WebGLProgram\n    private _secondPassViewportScaleLocation: WebGLUniformLocation\n    private _secondPassAtlasTexturesLocation: WebGLUniformLocation\n    private _unitQuadVerticesBuffer: WebGLBuffer\n    private _unitQuadElementIndicesBuffer: WebGLBuffer\n    private _glyphInstances: Float32Array\n    private _glyphInstancesBuffer: WebGLBuffer\n    private _vertexArrayObject: WebGLVertexArrayObject\n\n    constructor(\n        private _gl: WebGL2RenderingContext,\n        private _ligatureGrouper: ILigatureGrouper,\n        atlasOptions: IGlyphAtlasOptions,\n    ) {\n        this._glyphOverlapInPixels = atlasOptions.glyphPaddingInPixels\n        this._subpixelDivisor = atlasOptions.offsetGlyphVariantCount\n        this._devicePixelRatio = atlasOptions.devicePixelRatio\n        this._atlas = new GlyphAtlas(this._gl, atlasOptions)\n\n        this._firstPassProgram = createProgram(\n            this._gl,\n            vertexShaderSource,\n            firstPassFragmentShaderSource,\n        )\n        this._secondPassProgram = createProgram(\n            this._gl,\n            vertexShaderSource,\n            secondPassFragmentShaderSource,\n        )\n\n        this._firstPassViewportScaleLocation = this._gl.getUniformLocation(\n            this._firstPassProgram,\n            \"viewportScale\",\n        )\n        this._secondPassViewportScaleLocation = this._gl.getUniformLocation(\n            this._secondPassProgram,\n            \"viewportScale\",\n        )\n\n        this._firstPassAtlasTexturesLocation = this._gl.getUniformLocation(\n            this._firstPassProgram,\n            \"atlasTextures\",\n        )\n        this._secondPassAtlasTexturesLocation = this._gl.getUniformLocation(\n            this._secondPassProgram,\n            \"atlasTextures\",\n        )\n\n        this._createBuffers()\n        this._createVertexArrayObject()\n    }\n\n    public prefillAtlasWithCommonGlyphs() {\n        for (let asciiCode = 33; asciiCode <= 126; asciiCode++) {\n            const character = String.fromCharCode(asciiCode)\n\n            for (let variantIndex = 0; variantIndex < this._subpixelDivisor; variantIndex++) {\n                this._atlas.getRasterizedGlyph(character, false, false, variantIndex)\n                this._atlas.getRasterizedGlyph(character, true, false, variantIndex)\n                this._atlas.getRasterizedGlyph(character, false, true, variantIndex)\n                this._atlas.getRasterizedGlyph(character, true, true, variantIndex)\n            }\n        }\n    }\n\n    public draw(\n        columnCount: number,\n        rowCount: number,\n        getCell: (columnIndex: number, rowIndex: number) => ICell,\n        fontWidthInPixels: number,\n        fontHeightInPixels: number,\n        defaultForegroundColor: string,\n        viewportScaleX: number,\n        viewportScaleY: number,\n    ) {\n        const cellCount = columnCount * rowCount\n        this._recreateGlyphInstancesArrayIfRequired(cellCount)\n        const glyphInstanceCount = this._populateGlyphInstances(\n            columnCount,\n            rowCount,\n            getCell,\n            fontWidthInPixels,\n            fontHeightInPixels,\n            defaultForegroundColor,\n        )\n        this._drawGlyphInstances(glyphInstanceCount, viewportScaleX, viewportScaleY)\n    }\n\n    private _createBuffers() {\n        this._unitQuadVerticesBuffer = createUnitQuadVerticesBuffer(this._gl)\n        this._unitQuadElementIndicesBuffer = createUnitQuadElementIndicesBuffer(this._gl)\n        this._glyphInstancesBuffer = this._gl.createBuffer()\n    }\n\n    private _createVertexArrayObject() {\n        this._vertexArrayObject = this._gl.createVertexArray()\n        this._gl.bindVertexArray(this._vertexArrayObject)\n\n        this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, this._unitQuadElementIndicesBuffer)\n\n        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, this._unitQuadVerticesBuffer)\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.unitQuadVertex)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.unitQuadVertex,\n            2,\n            this._gl.FLOAT,\n            false,\n            0,\n            0,\n        )\n\n        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, this._glyphInstancesBuffer)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.targetOrigin)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.targetOrigin,\n            2,\n            this._gl.FLOAT,\n            false,\n            glyphInstanceSizeInBytes,\n            0,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.targetOrigin, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.targetSize)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.targetSize,\n            2,\n            this._gl.FLOAT,\n            false,\n            glyphInstanceSizeInBytes,\n            2 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.targetSize, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.textColorRGBA)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.textColorRGBA,\n            4,\n            this._gl.FLOAT,\n            false,\n            glyphInstanceSizeInBytes,\n            4 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.textColorRGBA, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.atlasLayerIndex)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.atlasLayerIndex,\n            1,\n            this._gl.FLOAT,\n            false,\n            glyphInstanceSizeInBytes,\n            8 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.atlasLayerIndex, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.atlasOrigin)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.atlasOrigin,\n            2,\n            this._gl.FLOAT,\n            false,\n            glyphInstanceSizeInBytes,\n            9 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.atlasOrigin, 1)\n\n        this._gl.enableVertexAttribArray(vertexShaderAttributes.atlasSize)\n        this._gl.vertexAttribPointer(\n            vertexShaderAttributes.atlasSize,\n            2,\n            this._gl.FLOAT,\n            false,\n            glyphInstanceSizeInBytes,\n            11 * Float32Array.BYTES_PER_ELEMENT,\n        )\n        this._gl.vertexAttribDivisor(vertexShaderAttributes.atlasSize, 1)\n    }\n\n    private _recreateGlyphInstancesArrayIfRequired(cellCount: number) {\n        const requiredArrayLength = cellCount * glyphInstanceFieldCount\n        if (!this._glyphInstances || this._glyphInstances.length < requiredArrayLength) {\n            this._glyphInstances = new Float32Array(requiredArrayLength)\n        }\n    }\n\n    private _populateGlyphInstances(\n        columnCount: number,\n        rowCount: number,\n        getCell: (columnIndex: number, rowIndex: number) => ICell,\n        fontWidthInPixels: number,\n        fontHeightInPixels: number,\n        defaultForegroundColor: string,\n    ) {\n        const pixelRatioAdaptedFontWidth = fontWidthInPixels * this._devicePixelRatio\n        const pixelRatioAdaptedFontHeight = fontHeightInPixels * this._devicePixelRatio\n        const pixelRatioAdaptedGlyphOverlap = this._glyphOverlapInPixels * this._devicePixelRatio\n\n        let glyphCount = 0\n        for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n            const cellGroups = groupCells(columnCount, rowIndex, getCell)\n\n            cellGroups.forEach(cellGroup => {\n                const { startColumnIndex, characters, bold, italic, foregroundColor } = cellGroup\n\n                const ligatureGroups = this._ligatureGrouper.getLigatureGroups(characters)\n\n                let offsetWithinCellGroup = 0\n                ligatureGroups.forEach(ligatureGroup => {\n                    const columnIndex = startColumnIndex + offsetWithinCellGroup\n                    const x = pixelRatioAdaptedFontWidth * columnIndex\n                    const y = pixelRatioAdaptedFontHeight * rowIndex\n                    const variantIndex =\n                        Math.round(x * this._subpixelDivisor) % this._subpixelDivisor\n                    const glyph = this._atlas.getRasterizedGlyph(\n                        ligatureGroup,\n                        bold,\n                        italic,\n                        variantIndex,\n                    )\n                    const colorToUse = foregroundColor || defaultForegroundColor || \"white\"\n                    const normalizedTextColor = normalizeColor(colorToUse)\n\n                    this._updateGlyphInstance(\n                        glyphCount,\n                        Math.round(x - glyph.variantOffset) - pixelRatioAdaptedGlyphOverlap,\n                        y - pixelRatioAdaptedGlyphOverlap,\n                        glyph,\n                        normalizedTextColor,\n                    )\n\n                    offsetWithinCellGroup += ligatureGroup.length\n                    glyphCount++\n                })\n            })\n        }\n\n        this._atlas.uploadTexture()\n\n        return glyphCount\n    }\n\n    private _drawGlyphInstances(\n        glyphCount: number,\n        viewportScaleX: number,\n        viewportScaleY: number,\n    ) {\n        this._gl.bindVertexArray(this._vertexArrayObject)\n        this._gl.enable(this._gl.BLEND)\n\n        this._gl.useProgram(this._firstPassProgram)\n\n        this._gl.uniform2f(this._firstPassViewportScaleLocation, viewportScaleX, viewportScaleY)\n        this._gl.uniform1i(this._firstPassAtlasTexturesLocation, 0)\n\n        this._gl.bindBuffer(this._gl.ARRAY_BUFFER, this._glyphInstancesBuffer)\n        this._gl.bufferData(this._gl.ARRAY_BUFFER, this._glyphInstances, this._gl.STREAM_DRAW)\n\n        this._gl.blendFuncSeparate(\n            this._gl.ZERO,\n            this._gl.ONE_MINUS_SRC_COLOR,\n            this._gl.ZERO,\n            this._gl.ONE,\n        )\n        this._gl.drawElementsInstanced(this._gl.TRIANGLES, 6, this._gl.UNSIGNED_BYTE, 0, glyphCount)\n\n        this._gl.useProgram(this._secondPassProgram)\n\n        this._gl.blendFuncSeparate(\n            this._gl.ONE,\n            this._gl.ONE,\n            this._gl.ONE,\n            this._gl.ONE_MINUS_SRC_ALPHA,\n        )\n\n        this._gl.uniform2f(this._secondPassViewportScaleLocation, viewportScaleX, viewportScaleY)\n        this._gl.uniform1i(this._secondPassAtlasTexturesLocation, 0)\n\n        this._gl.drawElementsInstanced(this._gl.TRIANGLES, 6, this._gl.UNSIGNED_BYTE, 0, glyphCount)\n    }\n\n    private _updateGlyphInstance(\n        index: number,\n        x: number,\n        y: number,\n        glyph: IRasterizedGlyph,\n        color: Float32Array,\n    ) {\n        const startOffset = glyphInstanceFieldCount * index\n        // targetOrigin\n        this._glyphInstances[0 + startOffset] = x\n        this._glyphInstances[1 + startOffset] = y\n        // targetSize\n        this._glyphInstances[2 + startOffset] = glyph.width\n        this._glyphInstances[3 + startOffset] = glyph.height\n        // textColorRGBA\n        this._glyphInstances[4 + startOffset] = color[0]\n        this._glyphInstances[5 + startOffset] = color[1]\n        this._glyphInstances[6 + startOffset] = color[2]\n        this._glyphInstances[7 + startOffset] = color[3]\n        // atlasLayerIndex\n        this._glyphInstances[8 + startOffset] = glyph.textureLayerIndex\n        // atlasOrigin\n        this._glyphInstances[9 + startOffset] = glyph.textureU\n        this._glyphInstances[10 + startOffset] = glyph.textureV\n        // atlasSize\n        this._glyphInstances[11 + startOffset] = glyph.textureWidth\n        this._glyphInstances[12 + startOffset] = glyph.textureHeight\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/groupCells.ts",
    "content": "import { ICell } from \"../../../neovim\"\nimport { ICellGroup } from \"./ICellGroup\"\n\nexport const groupCells = (\n    columnCount: number,\n    rowIndex: number,\n    getCell: (columnIndex: number, rowIndex: number) => ICell,\n) => {\n    const cellGroups: ICellGroup[] = []\n    for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {\n        const currentCell = getCell(columnIndex, rowIndex)\n        const currentCharacter = currentCell.character\n        const currentCellGroup = cellGroups.length && cellGroups[cellGroups.length - 1]\n\n        if (!currentCharacter || currentCharacter === \" \") {\n            continue\n        } else if (\n            currentCellGroup &&\n            cellStyleMatchesCellGroup(currentCell, currentCellGroup) &&\n            columnComesDirectlyAfterCellGroup(columnIndex, currentCellGroup)\n        ) {\n            currentCellGroup.characters.push(currentCharacter)\n        } else {\n            const newCellGroup = createNewCellGroup(columnIndex, currentCell)\n            cellGroups.push(newCellGroup)\n        }\n    }\n    return cellGroups\n}\n\nconst cellStyleMatchesCellGroup = (cell: ICell, cellGroup: ICellGroup) =>\n    cellGroup.foregroundColor === cell.foregroundColor &&\n    cellGroup.backgroundColor === cell.backgroundColor && // Maybe this isn't necessary; should we still group different backgrounds?\n    cellGroup.bold === cell.bold &&\n    cellGroup.italic === cell.italic &&\n    cellGroup.underline === cell.underline\n\nconst columnComesDirectlyAfterCellGroup = (columnIndex: number, cellGroup: ICellGroup) =>\n    columnIndex === cellGroup.startColumnIndex + cellGroup.characters.length\n\nconst createNewCellGroup = (startColumnIndex: number, startingCell: ICell) => {\n    const { character, foregroundColor, backgroundColor, bold, italic, underline } = startingCell\n    return {\n        startColumnIndex,\n        characters: [character],\n        foregroundColor,\n        backgroundColor,\n        bold,\n        italic,\n        underline,\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/TextRenderer/index.ts",
    "content": "export * from \"./TextRenderer\"\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/WebGLRenderer.ts",
    "content": "import { INeovimRenderer } from \"..\"\nimport { MinimalScreenForRendering } from \"../../neovim\"\nimport { normalizeColor } from \"./normalizeColor\"\nimport { SolidRenderer } from \"./SolidRenderer\"\nimport { TextRenderer } from \"./TextRenderer\"\nimport { IGlyphAtlasOptions, WebGLTextureSpaceExceededError } from \"./TextRenderer/GlyphAtlas\"\nimport {\n    ILigatureGrouper,\n    NoopLigatureGrouper,\n    OpenTypeLigatureGrouper,\n} from \"./TextRenderer/LigatureGrouper\"\n\nexport class WebGLRenderer implements INeovimRenderer {\n    private _editorElement: HTMLElement\n    private _ligatureGrouper: ILigatureGrouper = new NoopLigatureGrouper()\n    private _previousAtlasOptions: IGlyphAtlasOptions\n    private _textureSizeInPixels = 1024\n    private _textureLayerCount = 2\n\n    private _gl: WebGL2RenderingContext\n    private _solidRenderer: SolidRenderer\n    private _textRenderer: TextRenderer\n\n    public constructor(private _ligaturesEnabled: boolean) {}\n\n    public start(editorElement: HTMLElement): void {\n        this._editorElement = editorElement\n\n        const canvasElement = document.createElement(\"canvas\")\n        this._editorElement.innerHTML = \"\"\n        this._editorElement.appendChild(canvasElement)\n\n        this._gl = canvasElement.getContext(\"webgl2\") as WebGL2RenderingContext\n    }\n\n    public redrawAll(screenInfo: MinimalScreenForRendering): void {\n        if (!this._editorElement) {\n            return\n        }\n\n        this._updateCanvasDimensions()\n        this._createNewRendererIfRequired(screenInfo)\n        this._clear(screenInfo.backgroundColor)\n\n        try {\n            this._draw(screenInfo)\n        } catch (error) {\n            if (error instanceof WebGLTextureSpaceExceededError) {\n                this._textureLayerCount *= 2\n                this.redrawAll(screenInfo)\n            } else {\n                throw error\n            }\n        }\n    }\n\n    public draw(screenInfo: MinimalScreenForRendering): void {\n        this.redrawAll(screenInfo)\n    }\n\n    public onAction(action: any): void {\n        // do nothing\n    }\n\n    private _updateCanvasDimensions() {\n        const devicePixelRatio = window.devicePixelRatio\n        const canvas = this._gl.canvas\n        canvas.width = this._editorElement.offsetWidth * devicePixelRatio\n        canvas.height = this._editorElement.offsetHeight * devicePixelRatio\n        canvas.style.width = `${canvas.width / devicePixelRatio}px`\n        canvas.style.height = `${canvas.height / devicePixelRatio}px`\n    }\n\n    private _createNewRendererIfRequired(screenInfo: MinimalScreenForRendering) {\n        const {\n            fontHeightInPixels,\n            linePaddingInPixels,\n            fontFamily,\n            fontSize,\n            fontWeight,\n        } = screenInfo\n        const devicePixelRatio = window.devicePixelRatio\n        const offsetGlyphVariantCount = Math.max(Math.ceil(4 / devicePixelRatio), 1)\n        const atlasOptions = {\n            fontFamily,\n            fontSize,\n            fontWeight,\n            lineHeightInPixels: fontHeightInPixels,\n            linePaddingInPixels,\n            glyphPaddingInPixels: Math.ceil(fontHeightInPixels / 4),\n            devicePixelRatio,\n            offsetGlyphVariantCount,\n            textureSizeInPixels: this._textureSizeInPixels,\n            textureLayerCount: this._textureLayerCount,\n        } as IGlyphAtlasOptions\n\n        if (\n            !this._solidRenderer ||\n            !this._textRenderer ||\n            !this._previousAtlasOptions ||\n            !isShallowEqual(this._previousAtlasOptions, atlasOptions)\n        ) {\n            if (\n                (!this._previousAtlasOptions ||\n                    this._previousAtlasOptions.fontFamily !== fontFamily) &&\n                this._ligaturesEnabled\n            ) {\n                this._ligatureGrouper = new OpenTypeLigatureGrouper(fontFamily)\n            }\n\n            this._solidRenderer = new SolidRenderer(this._gl, atlasOptions.devicePixelRatio)\n            this._textRenderer = new TextRenderer(this._gl, this._ligatureGrouper, atlasOptions)\n            try {\n                this._textRenderer.prefillAtlasWithCommonGlyphs()\n            } catch (error) {\n                if (error instanceof WebGLTextureSpaceExceededError) {\n                    this._textureLayerCount *= 2\n                    this._createNewRendererIfRequired(screenInfo)\n                }\n            }\n\n            this._previousAtlasOptions = atlasOptions\n        }\n    }\n\n    private _clear(backgroundColor: string) {\n        const backgroundColorToUse = backgroundColor || \"black\"\n        const normalizedBackgroundColor = normalizeColor(backgroundColorToUse)\n        this._gl.clearColor(\n            normalizedBackgroundColor[0],\n            normalizedBackgroundColor[1],\n            normalizedBackgroundColor[2],\n            normalizedBackgroundColor[3],\n        )\n        this._gl.clear(this._gl.COLOR_BUFFER_BIT)\n    }\n\n    private _draw({\n        width: columnCount,\n        height: rowCount,\n        fontWidthInPixels,\n        fontHeightInPixels,\n        getCell,\n        foregroundColor,\n        backgroundColor,\n    }: MinimalScreenForRendering) {\n        const canvasWidth = this._gl.canvas.width\n        const canvasHeight = this._gl.canvas.height\n        const viewportScaleX = 2 / canvasWidth\n        const viewportScaleY = -2 / canvasHeight\n        this._gl.viewport(0, 0, canvasWidth, canvasHeight)\n\n        this._solidRenderer.draw(\n            columnCount,\n            rowCount,\n            getCell,\n            fontWidthInPixels,\n            fontHeightInPixels,\n            backgroundColor,\n            viewportScaleX,\n            viewportScaleY,\n        )\n        this._textRenderer.draw(\n            columnCount,\n            rowCount,\n            getCell,\n            fontWidthInPixels,\n            fontHeightInPixels,\n            foregroundColor,\n            viewportScaleX,\n            viewportScaleY,\n        )\n    }\n}\n\nfunction isShallowEqual<T>(objectA: T, objectB: T) {\n    for (const key in objectA) {\n        if (!(key in objectB) || objectA[key] !== objectB[key]) {\n            return false\n        }\n    }\n\n    for (const key in objectB) {\n        if (!(key in objectA) || objectA[key] !== objectB[key]) {\n            return false\n        }\n    }\n\n    return true\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/WebGLUtilities.ts",
    "content": "export const createProgram = (\n    gl: WebGL2RenderingContext,\n    vertexShaderSource: string,\n    fragmentShaderSource: string,\n) => {\n    const vertexShader = compileShader(gl, vertexShaderSource, gl.VERTEX_SHADER)\n    const fragmentShader = compileShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER)\n    return linkProgram(gl, vertexShader, fragmentShader)\n}\n\nconst compileShader = (gl: WebGL2RenderingContext, source: string, type: number) => {\n    const shader = gl.createShader(type)\n    gl.shaderSource(shader, source)\n    gl.compileShader(shader)\n\n    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n        const info = gl.getShaderInfoLog(shader)\n        throw new Error(\"Could not compile WebGL program: \\n\\n\" + info)\n    }\n\n    return shader\n}\n\nconst linkProgram = (\n    gl: WebGL2RenderingContext,\n    vertexShader: WebGLShader,\n    fragmentShader: WebGLShader,\n) => {\n    const program = gl.createProgram()\n    gl.attachShader(program, vertexShader)\n    gl.attachShader(program, fragmentShader)\n    gl.linkProgram(program)\n\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n        const info = gl.getProgramInfoLog(program)\n        throw new Error(\"Could not compile WebGL program: \\n\\n\" + info)\n    }\n    return program\n}\n\nconst unitQuadVertices = new Float32Array([1, 1, 1, 0, 0, 0, 0, 1])\n\nexport const createUnitQuadVerticesBuffer = (gl: WebGL2RenderingContext) => {\n    const unitQuadVerticesBuffer = gl.createBuffer()\n    gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer)\n    gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW)\n    return unitQuadVerticesBuffer\n}\n\nconst unitQuadElementIndices = new Uint8Array([0, 1, 3, 1, 2, 3])\n\nexport const createUnitQuadElementIndicesBuffer = (gl: WebGL2RenderingContext) => {\n    const unitQuadElementIndicesBuffer = gl.createBuffer()\n    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndicesBuffer)\n    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW)\n    return unitQuadElementIndicesBuffer\n}\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/index.ts",
    "content": "export * from \"./WebGLRenderer\"\n"
  },
  {
    "path": "browser/src/Renderer/WebGLRenderer/normalizeColor.ts",
    "content": "import colorNormalize from \"color-normalize\"\n\nconst cache = new Map<string, Float32Array>()\n\nexport const normalizeColor = (cssColor: string) => {\n    const cachedRgba = cache.get(cssColor)\n\n    if (cachedRgba) {\n        return cachedRgba\n    } else {\n        const rgba = colorNormalize(cssColor, \"float32\")\n        cache.set(cssColor, rgba)\n        return rgba\n    }\n}\n"
  },
  {
    "path": "browser/src/Renderer/index.ts",
    "content": "export * from \"./CanvasRenderer\"\nexport * from \"./WebGLRenderer\"\nexport * from \"./INeovimRenderer\"\n"
  },
  {
    "path": "browser/src/Services/AutoClosingPairs.ts",
    "content": "/**\n * AutoClosingPairs\n *\n * Service to enable auto-closing pair key bindings\n */\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { IBuffer } from \"./../Editor/BufferManager\"\nimport { Configuration } from \"./Configuration\"\nimport { EditorManager } from \"./EditorManager\"\nimport { InputManager } from \"./InputManager\"\nimport { LanguageManager } from \"./Language\"\n\nimport { NeovimInstance } from \"./../neovim\"\n\nexport interface IAutoClosingPair {\n    open: string\n    close: string\n    // TODO: Support `notIn` equivalent\n}\n\nexport const activate = (\n    configuration: Configuration,\n    editorManager: EditorManager,\n    inputManager: InputManager,\n    languageManager: LanguageManager,\n) => {\n    const insertModeFilter = () => editorManager.activeEditor.mode === \"insert\"\n\n    let subscriptions: Oni.DisposeFunction[] = []\n\n    const handleOpenCharacter = (\n        pair: IAutoClosingPair,\n        editor: Oni.Editor,\n        openCharacterSameAsClosed: boolean,\n    ) => () => {\n        Log.verbose(\"[AutoClosingPairs::handleOpenCharacter] \" + pair.open)\n        const neovim: NeovimInstance = editor.neovim as any\n        neovim.blockInput(async (inputFunc: any) => {\n            await checkOpenCharacter(inputFunc, pair, editor, openCharacterSameAsClosed)\n        })\n\n        return true\n    }\n\n    const handleBackspaceCharacter = (pairs: IAutoClosingPair[], editor: Oni.Editor) => () => {\n        Log.verbose(\"[AutoClosingPairs::handleBackspaceCharacter]\")\n        const neovim: NeovimInstance = editor.neovim as any\n        neovim.blockInput(async (inputFunc: any) => {\n            const activeBuffer = editor.activeBuffer\n            const lines = await activeBuffer.getLines(\n                activeBuffer.cursor.line,\n                activeBuffer.cursor.line + 1,\n            )\n            const line = lines[0]\n\n            const { column } = activeBuffer.cursor\n\n            const matchingPair = pairs.find(p => {\n                return column >= 1 && line[column] === p.close && line[column - 1] === p.open\n            })\n\n            if (matchingPair) {\n                // Remove the pairs\n                const beforePair = line.substring(0, column - 1)\n                const afterPair = line.substring(column + 1, line.length)\n\n                const pos = await neovim.callFunction(\"getpos\", [\".\"])\n                const [, oneBasedLine, oneBasedColumn] = pos\n                await editor.activeBuffer.setCursorPosition(oneBasedLine - 1, oneBasedColumn - 2)\n\n                await activeBuffer.setLines(\n                    activeBuffer.cursor.line,\n                    activeBuffer.cursor.line + 1,\n                    [beforePair + afterPair],\n                )\n            } else {\n                await inputFunc(\"<bs>\")\n            }\n        })\n\n        return true\n    }\n\n    const handleEnterCharacter = (pairs: IAutoClosingPair[], editor: Oni.Editor) => () => {\n        Log.verbose(\"[AutoClosingPairs::handleEnterCharacter]\")\n        const neovim: NeovimInstance = editor.neovim as any\n        editor.blockInput(async (inputFunc: Oni.InputCallbackFunction) => {\n            const activeBuffer = editor.activeBuffer\n\n            const lines = await activeBuffer.getLines(\n                activeBuffer.cursor.line,\n                activeBuffer.cursor.line + 1,\n            )\n            const line = lines[0]\n\n            const { column } = activeBuffer.cursor\n\n            const matchingPair = pairs.find(p => {\n                return column >= 1 && line[column] === p.close && line[column - 1] === p.open\n            })\n\n            if (matchingPair) {\n                const whiteSpacePrefix = getWhiteSpacePrefix(line)\n                const beforePair = line.substring(0, column)\n                const afterPair = line.substring(column, line.length)\n\n                const pos = await neovim.callFunction(\"getpos\", [\".\"])\n                const [, oneBasedLine] = pos\n                await activeBuffer.setLines(\n                    activeBuffer.cursor.line,\n                    activeBuffer.cursor.line + 1,\n                    [beforePair, whiteSpacePrefix, whiteSpacePrefix + afterPair],\n                )\n                await activeBuffer.setCursorPosition(oneBasedLine, whiteSpacePrefix.length)\n                await inputFunc(\"<tab>\")\n            } else {\n                await inputFunc(\"<enter>\")\n            }\n        })\n\n        return true\n    }\n\n    const handleCloseCharacter = (pair: IAutoClosingPair, editor: Oni.Editor) => () => {\n        Log.verbose(\"[AutoClosingPairs::handleCloseCharacter]\")\n        editor.blockInput(async (inputFunc: Oni.InputCallbackFunction) => {\n            const activeBuffer = editor.activeBuffer\n            const lines = await activeBuffer.getLines(\n                activeBuffer.cursor.line,\n                activeBuffer.cursor.line + 1,\n            )\n            const line = lines[0]\n            if (line[activeBuffer.cursor.column] === pair.close) {\n                await activeBuffer.setCursorPosition(\n                    activeBuffer.cursor.line,\n                    activeBuffer.cursor.column + 1,\n                )\n            } else {\n                await inputFunc(pair.close)\n            }\n        })\n\n        return true\n    }\n\n    const onBufferEnter = (newBuffer: Oni.Buffer) => {\n        if (!configuration.getValue(\"autoClosingPairs.enabled\")) {\n            Log.verbose(\"[Auto Closing Pairs] Not enabled.\")\n            return\n        }\n\n        if (subscriptions && subscriptions.length) {\n            subscriptions.forEach(df => df())\n        }\n\n        subscriptions = []\n\n        const autoClosingPairs = getAutoClosingPairs(configuration, newBuffer.language)\n\n        autoClosingPairs.forEach(pair => {\n            if (pair.open === pair.close) {\n                subscriptions.push(\n                    inputManager.bind(\n                        pair.open,\n                        handleOpenCharacter(pair, editorManager.activeEditor, true),\n                        insertModeFilter,\n                    ),\n                )\n            }\n\n            subscriptions.push(\n                inputManager.bind(\n                    pair.open,\n                    handleOpenCharacter(pair, editorManager.activeEditor, false),\n                    insertModeFilter,\n                ),\n            )\n            subscriptions.push(\n                inputManager.bind(\n                    pair.close,\n                    handleCloseCharacter(pair, editorManager.activeEditor),\n                    insertModeFilter,\n                ),\n            )\n        })\n\n        subscriptions.push(\n            inputManager.bind(\n                \"<bs>\",\n                handleBackspaceCharacter(autoClosingPairs, editorManager.activeEditor),\n                insertModeFilter,\n            ),\n        )\n        subscriptions.push(\n            inputManager.bind(\n                \"<enter>\",\n                handleEnterCharacter(autoClosingPairs, editorManager.activeEditor),\n                insertModeFilter,\n            ),\n        )\n    }\n\n    editorManager.anyEditor.onBufferEnter.subscribe(onBufferEnter)\n\n    const activeEditor = editorManager.activeEditor\n    if (activeEditor && activeEditor.activeBuffer) {\n        onBufferEnter(activeEditor.activeBuffer)\n    }\n}\n\nconst nonWhiteSpaceRegEx = /\\S/\n\nexport const getWhiteSpacePrefix = (str: string): string => {\n    const firstIndex = str.search(nonWhiteSpaceRegEx)\n\n    if (firstIndex === -1) {\n        return \"\"\n    } else {\n        return str.substring(0, firstIndex)\n    }\n}\n\nexport const checkOpenCharacter = async (\n    inputFunc: any,\n    pair: IAutoClosingPair,\n    editor: Oni.Editor,\n    openCharacterSameAsClosed: boolean,\n): Promise<void> => {\n    // TODO: PERFORMANCE: Look at how to collapse this instead of needed multiple asynchronous calls.\n\n    const activeBuffer = editor.activeBuffer as IBuffer\n\n    if (openCharacterSameAsClosed) {\n        const lines = await (activeBuffer as any).getLines(\n            activeBuffer.cursor.line,\n            activeBuffer.cursor.line + 1,\n            false,\n        )\n        const currentLine = lines[0]\n\n        if (currentLine[activeBuffer.cursor.column] === pair.open) {\n            await activeBuffer.setCursorPosition(\n                activeBuffer.cursor.line,\n                activeBuffer.cursor.column + 1,\n            )\n\n            return\n        }\n    }\n\n    await inputFunc(pair.open + pair.close)\n\n    const pos = await activeBuffer.getCursorPosition()\n    await editor.activeBuffer.setCursorPosition(pos.line, pos.character - 1)\n}\n\nconst getAutoClosingPairs = (\n    configuration: Configuration,\n    language: string,\n): IAutoClosingPair[] => {\n    const languagePairs = configuration.getValue(`language.${language}.autoClosingPairs`)\n\n    if (languagePairs) {\n        return languagePairs\n    } else {\n        return configuration.getValue(\"autoClosingPairs.default\") || []\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/AutoUpdate.ts",
    "content": "/**\n * AutoUpdate.ts\n *\n * Provides auto-update functionality\n * - Check for update\n * - Notifies when an update is available\n */\n\nimport * as os from \"os\"\n\nimport { Observable } from \"rxjs/Observable\"\nimport { Subject } from \"rxjs/Subject\"\n\nimport { getMetadata } from \"./Metadata\"\n\nimport { configuration } from \"./Configuration\"\n\nexport interface IAutoUpdater {\n    onUpdateNotAvailable: Observable<void>\n    onUpdateAvailable: Observable<void>\n    checkForUpdates(url: string): void\n}\n\nexport const constructFeedUrl = async (baseUrl: string) => {\n    const plat = os.platform()\n    const { version } = await getMetadata()\n\n    const isDevelopment = process.env[\"NODE_ENV\"] === \"development\" // tslint:disable-line no-string-literal\n    const channel = isDevelopment ? \"development\" : \"release\"\n\n    return baseUrl + `?platform=${plat}&version=${version}&channel=${channel}`\n}\n\nexport class AutoUpdater implements IAutoUpdater {\n    private _onUpdateAvailable: Subject<void> = new Subject()\n    private _onUpdateNotAvailable: Subject<void> = new Subject()\n\n    public get onUpdateNotAvailable(): Observable<void> {\n        return this._onUpdateNotAvailable\n    }\n    public get onUpdateAvailable(): Observable<void> {\n        return this._onUpdateAvailable\n    }\n\n    public checkForUpdates(url: string): void {\n        if (!configuration.getValue(\"autoUpdate.enabled\")) {\n            return\n        }\n\n        fetch(url).then(response => {\n            if (response.status === 204) {\n                this._onUpdateNotAvailable.next()\n            } else {\n                this._onUpdateAvailable.next()\n            }\n        })\n    }\n}\n\nexport const autoUpdater = new AutoUpdater()\n"
  },
  {
    "path": "browser/src/Services/Automation.ts",
    "content": "/**\n * Automation.ts\n *\n * Helper methods for running automated tests\n */\n\nimport { remote } from \"electron\"\n\nimport * as OniApi from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport * as App from \"./../App\"\nimport * as Utility from \"./../Utility\"\n\nimport { getUserConfigFilePath } from \"./Configuration\"\nimport { editorManager } from \"./EditorManager\"\nimport { inputManager } from \"./InputManager\"\n\nimport { IKey, parseKeysFromVimString } from \"./../Input/KeyParser\"\n\nexport interface ITestResult {\n    passed: boolean\n    exception?: any\n}\n\nimport { Oni } from \"./../Plugins/Api/Oni\"\n\nexport class Automation implements OniApi.Automation.Api {\n    public sendKeys(keys: string): void {\n        Log.info(\"[AUTOMATION] Sending keys: \" + keys)\n\n        if (!inputManager.handleKey(keys)) {\n            Log.info(\"[AUTOMATION] InputManager did not handle key: \" + keys)\n            const anyEditor: any = editorManager.activeEditor as any\n            anyEditor.input(keys)\n        }\n    }\n\n    public sendKeysV2(keys: string): void {\n        const parsedKeys = parseKeysFromVimString(keys)\n\n        const contents = remote.getCurrentWebContents()\n\n        const convertCharacter = (key: string) => {\n            switch (key.toLowerCase()) {\n                case \"lt\":\n                    return \"<\"\n                case \"cr\":\n                    return \"enter\"\n                default:\n                    return key\n            }\n        }\n\n        const convertModifiers = (key: IKey): string[] => {\n            const ret: string[] = []\n\n            if (key.control) {\n                ret.push(\"control\")\n            }\n            if (key.alt) {\n                ret.push(\"alt\")\n            }\n            if (key.meta) {\n                ret.push(\"meta\")\n            }\n            if (key.shift) {\n                ret.push(\"shift\")\n            }\n\n            return ret\n        }\n\n        parsedKeys.chord.forEach(key => {\n            const character = convertCharacter(key.character)\n            const modifiers = convertModifiers(key)\n            contents.sendInputEvent({ keyCode: character, modifiers, type: \"keyDown\" } as any)\n            contents.sendInputEvent({ keyCode: character, modifiers, type: \"char\" } as any)\n            contents.sendInputEvent({ keyCode: character, type: \"keyUp\" } as any)\n        })\n    }\n\n    public async sleep(time: number = 1000): Promise<void> {\n        Log.info(\"[AUTOMATION] Sleeping for \" + time + \"ms\")\n        return new Promise<void>(r => window.setTimeout(() => r(), time))\n    }\n\n    public async waitFor(condition: () => boolean, timeout: number = 10000): Promise<void> {\n        Log.info(\n            \"[AUTOMATION] Starting wait - limit: \" +\n                timeout +\n                \" condition: \" +\n                condition.toString(),\n        )\n        let time = 0\n        const interval = 1000\n\n        while (time <= timeout) {\n            if (condition()) {\n                Log.info(\"[AUTOMATION] Wait condition met at: \" + time)\n                return\n            }\n            await this.sleep(interval)\n            time += interval\n            Log.info(\"[AUTOMATION] Wait condition still not met: \" + time + \" / \" + timeout)\n        }\n\n        Log.info(\"[AUTOMATION]: waitFor timeout expired for condition: \" + condition.toString())\n\n        throw new Error(\"waitFor: Timeout expired\")\n    }\n\n    public async waitForEditors(): Promise<void> {\n        Log.info(\"[AUTOMATION] Waiting for startup...\")\n        await App.waitForStart()\n        Log.info(\"[AUTOMATION] Startup complete!\")\n    }\n\n    public async runTest(testPath: string): Promise<void> {\n        const containerElement = this._getOrCreateTestContainer(\"automated-test-container\")\n        containerElement.innerHTML = \"\"\n\n        const testPath2 = testPath\n\n        Log.enableVerboseLogging()\n        try {\n            Log.info(\"[AUTOMATION] Starting test: \" + testPath)\n            Log.info(\"[AUTOMATION] Configuration path: \" + getUserConfigFilePath())\n            const testCase: any = Utility.nodeRequire(testPath2)\n            const oni = new Oni()\n\n            this._initializeBrowseWindow()\n\n            await testCase.test(oni)\n            Log.info(\"[AUTOMATION] Completed test: \" + testPath)\n\n            await this._reportResult(true)\n        } catch (ex) {\n            await this._reportResult(false, ex)\n        } finally {\n            this._reportWindowSize()\n        }\n    }\n\n    private _initializeBrowseWindow(): void {\n        const win = remote.getCurrentWindow()\n        win.maximize()\n        win.focus()\n\n        this._reportWindowSize()\n    }\n\n    private _reportWindowSize(): void {\n        const win = remote.getCurrentWindow()\n        const size = win.getContentSize()\n        Log.info(`[AUTOMATION]: Window size reported as ${size}`)\n        Log.info(`[AUTOMATION]: Window focus state: ${win.isFocused()}`)\n        Log.info(`[AUTOMATION]: Is off-screen rendering: ${win.webContents.isOffscreen()}`)\n    }\n\n    private _getOrCreateTestContainer(className: string): HTMLDivElement {\n        const containerElement = document.body.getElementsByClassName(className)\n\n        if (containerElement && containerElement.length > 0) {\n            return containerElement[0] as HTMLDivElement\n        }\n\n        const container = this._createElement(className, document.body)\n        return container\n    }\n\n    private async _reportResult(passed: boolean, exception?: any): Promise<void> {\n        Log.info(\"[AUTOMATION] Quitting...\")\n        // Close all Neovim instances, but don't close the browser window... let Spectron\n        // take care of that.\n\n        // TODO: Bring this back once the 'quit' logic is more stable!\n        // editorManager.setCloseWhenNoEditors(false)\n        // try {\n        //     await App.quit()\n        // } catch (ex) {\n        //     Log.error(ex)\n        // }\n        // Log.info(\"[AUTOMATION] Quit successfully\")\n\n        const resultElement = this._createElement(\n            \"automated-test-result\",\n            this._getOrCreateTestContainer(\"automated-test-container\"),\n        )\n\n        if (exception && exception.code && exception.code === \"ERR_ASSERTION\") {\n            resultElement.textContent = JSON.stringify({\n                passed,\n                exception,\n                expected: exception.expected,\n                actual: exception.actual,\n                message: exception.message,\n                operator: exception.operator,\n            })\n        } else {\n            resultElement.textContent = JSON.stringify({\n                passed,\n                exception: exception || null,\n            })\n        }\n    }\n\n    private _createElement(className: string, parentElement: HTMLElement): HTMLDivElement {\n        const elem = document.createElement(\"div\")\n        elem.className = className\n        parentElement.appendChild(elem)\n        return elem\n    }\n}\n\nexport const automation = new Automation()\n"
  },
  {
    "path": "browser/src/Services/Bookmarks/BookmarksPane.tsx",
    "content": "/**\n * BookmarksPane.tsx\n *\n * UX for rendering the bookmarks experience in the sidebar\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nimport * as path from \"path\"\n\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { SidebarPane } from \"./../Sidebar\"\nimport { IBookmark, IBookmarksProvider } from \"./index\"\n\nimport { SidebarEmptyPaneView } from \"./../../UI/components/SidebarEmptyPaneView\"\nimport { SidebarContainerView, SidebarItemView } from \"./../../UI/components/SidebarItemView\"\nimport { VimNavigator } from \"./../../UI/components/VimNavigator\"\n\nexport class BookmarksPane implements SidebarPane {\n    private _onEnter = new Event<void>()\n    private _onLeave = new Event<void>()\n\n    constructor(private _bookmarksProvider: IBookmarksProvider) {}\n\n    public get id(): string {\n        return \"oni.sidebar.bookmarks\"\n    }\n\n    public get title(): string {\n        return \"Marks\"\n    }\n\n    public enter(): void {\n        this._onEnter.dispatch()\n    }\n\n    public leave(): void {\n        this._onLeave.dispatch()\n    }\n\n    public render(): JSX.Element {\n        return (\n            <BookmarksPaneView\n                bookmarksProvider={this._bookmarksProvider}\n                onEnter={this._onEnter}\n                onLeave={this._onLeave}\n            />\n        )\n    }\n}\n\nexport interface IBookmarksPaneViewProps {\n    bookmarksProvider: IBookmarksProvider\n    onEnter: IEvent<void>\n    onLeave: IEvent<void>\n}\n\nexport interface IBookmarksPaneViewState {\n    bookmarks: IBookmark[]\n    isActive: boolean\n\n    isGlobalSectionExpanded: boolean\n    isLocalSectionExpanded: boolean\n}\n\nconst BookmarkItemWrapper = styled.div`\n    display: flex;\n    flex-direction: row;\n\n    justify-content: center;\n    align-items; center;\n    margin-left: 8px;\n`\n\nconst BookmarkIconWrapper = styled.div`\n    padding: 8px;\n    margin: 4px;\n    background-color: rgba(0, 0, 0, 0.2);\n    flex: 0 0 auto;\n`\n\nconst BookmarkDescriptionWrapper = styled.div`\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n\n    margin-left: 8px;\n    flex: 1 1 auto;\n    overflow: hidden;\n`\n\nconst BookmarkTitleWrapper = styled.div`\n    text-overflow: ellipsis;\n    white-space: nowrap;\n`\n\nconst BookmarkLocationWrapper = styled.div`\n    font-size: 0.8em;\n    text-overflow: ellipsis;\n`\n\nconst BookmarkItemView = (props: { bookmark: IBookmark }) => {\n    return (\n        <BookmarkItemWrapper>\n            <BookmarkIconWrapper>{props.bookmark.id}</BookmarkIconWrapper>\n            <BookmarkDescriptionWrapper>\n                <BookmarkTitleWrapper>{path.basename(props.bookmark.text)}</BookmarkTitleWrapper>\n                <BookmarkLocationWrapper>\n                    {props.bookmark.line + \", \" + props.bookmark.column}\n                </BookmarkLocationWrapper>\n            </BookmarkDescriptionWrapper>\n        </BookmarkItemWrapper>\n    )\n}\n\nexport class BookmarksPaneView extends React.PureComponent<\n    IBookmarksPaneViewProps,\n    IBookmarksPaneViewState\n> {\n    private _subscriptions: IDisposable[] = []\n\n    constructor(props: IBookmarksPaneViewProps) {\n        super(props)\n        this.state = {\n            bookmarks: this.props.bookmarksProvider.bookmarks,\n            isActive: false,\n            isGlobalSectionExpanded: true,\n            isLocalSectionExpanded: true,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._clearExistingSubscriptions()\n\n        const s1 = this.props.bookmarksProvider.onBookmarksUpdated.subscribe(() => {\n            this.setState({\n                bookmarks: this.props.bookmarksProvider.bookmarks,\n            })\n        })\n\n        const s2 = this.props.onEnter.subscribe(() => this.setState({ isActive: true }))\n        const s3 = this.props.onLeave.subscribe(() => this.setState({ isActive: false }))\n\n        this._subscriptions = [s1, s2, s3]\n    }\n\n    public componentWillUnmount(): void {\n        this._clearExistingSubscriptions()\n    }\n\n    public render(): JSX.Element {\n        if (this.state.bookmarks.length === 0) {\n            return (\n                <SidebarEmptyPaneView\n                    active={this.state.isActive}\n                    contentsText=\"No bookmarks, yet!\"\n                />\n            )\n        } else {\n            const globalMarks = this.state.bookmarks.filter(bm => bm.group === \"Global Marks\")\n            const localMarks = this.state.bookmarks.filter(bm => bm.group === \"Local Marks\")\n\n            const globalMarkIds = this.state.isGlobalSectionExpanded\n                ? globalMarks.map(bm => bm.id)\n                : []\n            const localMarkIds = this.state.isLocalSectionExpanded\n                ? localMarks.map(bm => bm.id)\n                : []\n\n            const mapToItems = (selectedId: string) => (bm: IBookmark) => (\n                <SidebarItemView\n                    key={bm.id}\n                    text={<BookmarkItemView bookmark={bm} />}\n                    isFocused={selectedId === bm.id}\n                    isContainer={false}\n                    indentationLevel={0}\n                    onClick={() => this._onSelected(bm.id)}\n                />\n            )\n\n            const allIds = [\n                \"container.global\",\n                ...globalMarkIds,\n                \"container.local\",\n                ...localMarkIds,\n            ]\n\n            return (\n                <VimNavigator\n                    ids={allIds}\n                    active={this.state.isActive}\n                    onSelected={id => this._onSelected(id)}\n                    render={selectedId => {\n                        const mapFunc = mapToItems(selectedId)\n                        return (\n                            <div>\n                                <SidebarContainerView\n                                    text=\"Global Marks\"\n                                    isExpanded={this.state.isGlobalSectionExpanded}\n                                    isFocused={selectedId === \"container.global\"}\n                                    onClick={() => this._onSelected(\"container.global\")}\n                                >\n                                    {globalMarks.map(mapFunc)}\n                                </SidebarContainerView>\n                                <SidebarContainerView\n                                    text=\"Local Marks\"\n                                    isExpanded={this.state.isLocalSectionExpanded}\n                                    isFocused={selectedId === \"container.local\"}\n                                    onClick={() => this._onSelected(\"container.local\")}\n                                >\n                                    {localMarks.map(mapFunc)}\n                                </SidebarContainerView>\n                            </div>\n                        )\n                    }}\n                />\n            )\n        }\n    }\n\n    private _onSelected(id: string): void {\n        if (id === \"container.global\") {\n            this.setState({ isGlobalSectionExpanded: !this.state.isGlobalSectionExpanded })\n        } else if (id === \"container.local\") {\n            this.setState({ isLocalSectionExpanded: !this.state.isLocalSectionExpanded })\n        }\n    }\n\n    private _clearExistingSubscriptions(): void {\n        this._subscriptions.forEach(sub => sub.dispose())\n        this._subscriptions = []\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Bookmarks/index.ts",
    "content": "import { Event, IEvent } from \"oni-types\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { SidebarManager } from \"./../Sidebar\"\n\nimport { BookmarksPane } from \"./BookmarksPane\"\n\nimport { INeovimMarkInfo, INeovimMarks } from \"./../../neovim\"\n\nexport interface IBookmark {\n    group: string\n    text: string\n    line: number\n    column: number\n    id: string\n}\n\nexport interface IBookmarksProvider {\n    bookmarks: IBookmark[]\n    onBookmarksUpdated: IEvent<void>\n    selectBookmark(bookmark: IBookmark): void\n}\n\nconst marksToBookmarks = (mark: INeovimMarkInfo): IBookmark => ({\n    id: mark.mark,\n    group: mark.global ? \"Global Marks\" : \"Local Marks\",\n    text: mark.text,\n    line: mark.line,\n    column: mark.column,\n})\n\nexport class NeovimBookmarksProvider implements IBookmarksProvider {\n    private _lastBookmarks: IBookmark[] = []\n    private _onBookmarksUpdated = new Event<void>()\n\n    public get bookmarks(): IBookmark[] {\n        return this._lastBookmarks\n    }\n\n    public get onBookmarksUpdated(): IEvent<void> {\n        return this._onBookmarksUpdated\n    }\n\n    constructor(private _neovimMarks: INeovimMarks) {\n        this._neovimMarks.onMarksUpdated.subscribe(marks => {\n            this._lastBookmarks = marks.map(marksToBookmarks)\n\n            this._onBookmarksUpdated.dispatch()\n        })\n    }\n\n    public selectBookmark(bookmark: IBookmark): void {\n        alert(\"Selecting bookmark: \" + bookmark.id)\n    }\n}\n\nlet _bookmarks: IBookmarksProvider\n\nexport const activate = (\n    configuration: Configuration,\n    editorManager: EditorManager,\n    sidebarManager: SidebarManager,\n) => {\n    const marksEnabled =\n        configuration.getValue(\"sidebar.enabled\") && configuration.getValue(\"sidebar.marks.enabled\")\n\n    if (!marksEnabled) {\n        return\n    }\n\n    // TODO: Push bookmarks provider to editor\n    const neovim: any = editorManager.activeEditor.neovim\n    neovim.marks.watchMarks()\n    _bookmarks = new NeovimBookmarksProvider(neovim.marks)\n\n    sidebarManager.add(\"bookmark\", new BookmarksPane(_bookmarks))\n}\n\nexport const getInstance = (): IBookmarksProvider => _bookmarks\n"
  },
  {
    "path": "browser/src/Services/Browser/AddressBarView.tsx",
    "content": "/**\n * AddressBarView.tsx\n *\n * Component to manage address bar state (whether it is focused or not)\n */\n\nimport * as React from \"react\"\nimport styled from \"styled-components\"\n\nimport { TextInputView } from \"./../../UI/components/LightweightText\"\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\n\nimport { withProps } from \"./../../UI/components/common\"\n\nconst AddressBarWrapper = styled.div`\n    width: 100%;\n\n    height: 2.5em;\n    line-height: 2.5em;\n\n    text-align: left;\n`\n\nconst EditableAddressBarWrapper = withProps<{}>(styled.div)`\n\n    border: 1px solid ${p => p.theme[\"highlight.mode.insert.background\"]};\n\n\n    &, & input {\n        background-color: ${p => p.theme[\"editor.background\"]};\n        color: ${p => p.theme[\"editor.foreground\"]};\n    }\n\n    & input {\n        margin-left: 1em;\n    }\n`\n\nexport interface IAddressBarViewProps {\n    url: string\n\n    onAddressChanged: (newAddress: string) => void\n}\n\nexport interface IAddressBarViewState {\n    isActive: boolean\n}\n\nexport class AddressBarView extends React.PureComponent<\n    IAddressBarViewProps,\n    IAddressBarViewState\n> {\n    constructor(props: IAddressBarViewProps) {\n        super(props)\n\n        this.state = {\n            isActive: false,\n        }\n    }\n\n    public render(): JSX.Element {\n        const contents = this.state.isActive ? this._renderTextInput() : this._renderAddressSpan()\n\n        return <AddressBarWrapper>{contents}</AddressBarWrapper>\n    }\n\n    private _renderTextInput(): JSX.Element {\n        return (\n            <EditableAddressBarWrapper>\n                <TextInputView\n                    defaultValue={this.props.url}\n                    onComplete={evt => {\n                        this._onComplete(evt)\n                    }}\n                    onCancel={() => this._onCancel()}\n                />\n            </EditableAddressBarWrapper>\n        )\n    }\n\n    private _renderAddressSpan(): JSX.Element {\n        return (\n            <Sneakable callback={() => this._setActive()} tag={\"browser.address\"}>\n                <span onClick={() => this._setActive()}>{this.props.url}</span>\n            </Sneakable>\n        )\n    }\n\n    private _setActive(): void {\n        this.setState({\n            isActive: true,\n        })\n    }\n\n    private _onCancel(): void {\n        this.setState({\n            isActive: false,\n        })\n    }\n\n    private _onComplete(val: string): void {\n        this.props.onAddressChanged(val)\n\n        this._onCancel()\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Browser/BrowserButtonView.tsx",
    "content": "/**\n * BrowserButtonView.tsx\n *\n * Component for the browser buttons on the address bar of the integrated browser\n */\n\nimport * as React from \"react\"\nimport styled from \"styled-components\"\n\nimport { Icon, IconSize } from \"./../../UI/Icon\"\n\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\n\nconst BrowserButtonWrapper = styled.div`\n    width: 2.5em;\n    height: 2.5em;\n    flex: 0 0 auto;\n    opacity: 0.9;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    &:hover {\n        opacity: 1;\n        box-shadow: 0 -8px 20px 0 rgba(0, 0, 0, 0.2);\n    }\n`\n\nexport interface IBrowserButtonViewProps {\n    onClick: () => void\n    icon: string\n}\n\nexport const BrowserButtonView = (props: IBrowserButtonViewProps): JSX.Element => {\n    return (\n        <Sneakable callback={props.onClick}>\n            <BrowserButtonWrapper onClick={props.onClick}>\n                <Icon name={props.icon} size={IconSize.Large} />\n            </BrowserButtonWrapper>\n        </Sneakable>\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Browser/BrowserView.tsx",
    "content": "/**\n * oni-layer-browser/index.ts\n *\n * Entry point for browser integration plugin\n */\n\nimport * as path from \"path\"\n\nimport * as React from \"react\"\nimport styled from \"styled-components\"\n\nimport { WebviewTag } from \"electron\"\nimport * as Oni from \"oni-api\"\nimport { IDisposable, IEvent } from \"oni-types\"\n\nimport { Configuration } from \"./../../Services/Configuration\"\nimport { getInstance as getAchievementsInstance } from \"./../../Services/Learning/Achievements\"\nimport { getInstance as getSneakInstance, ISneakInfo } from \"./../../Services/Sneak\"\nimport { focusManager } from \"./../FocusManager\"\n\nimport { AddressBarView } from \"./AddressBarView\"\nimport { BrowserButtonView } from \"./BrowserButtonView\"\n\nconst Column = styled.div`\n    pointer-events: auto;\n\n    display: flex;\n    flex-direction: column;\n\n    width: 100%;\n    height: 100%;\n`\n\nconst BrowserControlsWrapper = styled.div`\n    display: flex;\n    flex-direction: row;\n    flex: 0 0 auto;\n    user-select: none;\n\n    height: 3em;\n    width: 100%;\n    background-color: ${props => props.theme[\"editor.background\"]};\n    color: ${props => props.theme[\"editor.foreground\"]};\n`\n\nconst BrowserViewWrapper = styled.div`\n    flex: 1 1 auto;\n\n    width: 100%;\n    height: 100%;\n    position: relative;\n\n    webview {\n        height: 100%;\n        width: 100%;\n    }\n`\n\nexport interface IBrowserViewProps {\n    initialUrl: string\n\n    configuration: Configuration\n\n    debug: IEvent<void>\n    goBack: IEvent<void>\n    goForward: IEvent<void>\n    reload: IEvent<void>\n    scrollUp: IEvent<void>\n    scrollDown: IEvent<void>\n    scrollLeft: IEvent<void>\n    scrollRight: IEvent<void>\n\n    webviewRef?: (webviewTag: WebviewTag) => void\n    onFocusTag?: (tagName: string | null) => void\n}\n\nexport interface IBrowserViewState {\n    url: string\n}\n\nexport interface SneakInfoFromBrowser {\n    id: string\n    rectangle: Oni.Shapes.Rectangle\n}\n\nexport class BrowserView extends React.PureComponent<IBrowserViewProps, IBrowserViewState> {\n    public _webviewElement: WebviewTag\n    private _elem: HTMLElement\n    private _disposables: IDisposable[] = []\n\n    constructor(props: IBrowserViewProps) {\n        super(props)\n\n        this.state = {\n            url: props.initialUrl,\n        }\n    }\n\n    public componentDidMount(): void {\n        const d1 = this.props.goBack.subscribe(() => this._goBack())\n        const d2 = this.props.goForward.subscribe(() => this._goForward())\n        const d3 = this.props.reload.subscribe(() => this._reload())\n        const d4 = this.props.debug.subscribe(() => this._openDebugger())\n        const scrollDown = this.props.scrollDown.subscribe(() => this._scrollDown())\n        const scrollUp = this.props.scrollUp.subscribe(() => this._scrollUp())\n        const scrollRight = this.props.scrollRight.subscribe(() => this._scrollRight())\n        const scrollLeft = this.props.scrollLeft.subscribe(() => this._scrollLeft())\n\n        const d5 = getSneakInstance().addSneakProvider(async (): Promise<ISneakInfo[]> => {\n            if (this._webviewElement) {\n                const promise = new Promise<SneakInfoFromBrowser[]>(resolve => {\n                    this._webviewElement.executeJavaScript(\n                        \"window['__oni_sneak_collector__']()\",\n                        null,\n                        result => {\n                            resolve(result)\n                        },\n                    )\n                })\n\n                const webviewDimensions: ClientRect = this._webviewElement.getBoundingClientRect()\n\n                const sneaks: SneakInfoFromBrowser[] = await promise\n\n                return sneaks.map(s => {\n                    const callbackFunction = (id: string) => () => this._triggerSneak(id)\n                    const zoomFactor = this._getZoomFactor()\n                    return {\n                        rectangle: Oni.Shapes.Rectangle.create(\n                            webviewDimensions.left + s.rectangle.x * zoomFactor,\n                            webviewDimensions.top + s.rectangle.y * zoomFactor,\n                            s.rectangle.width * zoomFactor,\n                            s.rectangle.height * zoomFactor,\n                        ),\n                        callback: callbackFunction(s.id),\n                    }\n                })\n            }\n\n            return []\n        })\n\n        const d6 = this.props.configuration.onConfigurationChanged.subscribe(val => {\n            const newZoomFactor = val[\"browser.zoomFactor\"]\n\n            if (this._webviewElement && newZoomFactor) {\n                this._webviewElement.setZoomFactor(newZoomFactor)\n            }\n        })\n\n        this._disposables = this._disposables.concat([\n            d1,\n            d2,\n            d3,\n            d4,\n            d5,\n            d6,\n            scrollUp,\n            scrollDown,\n            scrollLeft,\n            scrollRight,\n        ])\n        this._initializeElement(this._elem)\n    }\n\n    public _triggerSneak(id: string): void {\n        if (this._webviewElement) {\n            this._webviewElement.focus()\n            this._webviewElement.executeJavaScript(`window[\"__oni_sneak_execute__\"](\"${id}\")`, true)\n\n            getAchievementsInstance().notifyGoal(\"oni.goal.sneakIntoBrowser\")\n        }\n    }\n\n    public componentWillUnmount(): void {\n        this._webviewElement = null\n        this._disposables.forEach(d => d.dispose())\n        this._disposables = []\n    }\n\n    public render(): JSX.Element {\n        return (\n            <Column key=\"test2\">\n                <BrowserControlsWrapper>\n                    <BrowserButtonView icon={\"chevron-left\"} onClick={this._goBack} />\n                    <BrowserButtonView icon={\"chevron-right\"} onClick={this._goForward} />\n                    <BrowserButtonView icon={\"undo\"} onClick={this._reload} />\n                    <AddressBarView\n                        url={this.state.url}\n                        onAddressChanged={url => this._navigate(url)}\n                    />\n                    <BrowserButtonView icon={\"bug\"} onClick={this._openDebugger} />\n                </BrowserControlsWrapper>\n                <BrowserViewWrapper>\n                    <div\n                        ref={elem => (this._elem = elem)}\n                        style={{\n                            position: \"absolute\",\n                            top: \"0px\",\n                            left: \"0px\",\n                            right: \"0px\",\n                            bottom: \"0px\",\n                        }}\n                        key={\"test\"}\n                    />\n                </BrowserViewWrapper>\n            </Column>\n        )\n    }\n\n    public prefixUrl = (url: string) => {\n        // Regex Explainer - match at the beginning of the string ^\n        // brackets to match the selection not partial match like ://\n        // match http or https, then match ://\n        const hasValidProtocol = /^(https?:)\\/\\//i\n        if (url && !hasValidProtocol.test(url)) {\n            return `http://${url}`\n        }\n        return url\n    }\n\n    public _scrollLeft = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.sendInputEvent({\n                type: \"keyDown\",\n                keyCode: \"Left\",\n                canScroll: true,\n                modifiers: [\"isAutoRepeat\"],\n            })\n        }\n    }\n\n    public _scrollRight = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.sendInputEvent({\n                type: \"keyDown\",\n                keyCode: \"Right\",\n                canScroll: true,\n                modifiers: [\"isAutoRepeat\"],\n            })\n        }\n    }\n\n    public _scrollDown = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.sendInputEvent({\n                type: \"keyDown\",\n                keyCode: \"Down\",\n                canScroll: true,\n                modifiers: [\"isAutoRepeat\"],\n            })\n        }\n    }\n\n    public _scrollUp = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.sendInputEvent({\n                type: \"keyDown\",\n                keyCode: \"Up\",\n                canScroll: true,\n                modifiers: [\"isAutoRepeat\"],\n            })\n        }\n    }\n\n    private _navigate = (url: string): void => {\n        if (this._webviewElement) {\n            this._webviewElement.src = this.prefixUrl(url)\n\n            this.setState({\n                url,\n            })\n        }\n    }\n\n    private _goBack = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.goBack()\n        }\n    }\n\n    private _goForward = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.goForward()\n        }\n    }\n\n    private _openDebugger = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.openDevTools()\n        }\n    }\n\n    private _reload = (): void => {\n        if (this._webviewElement) {\n            this._webviewElement.reload()\n        }\n    }\n\n    private _getZoomFactor = (): number => {\n        return this.props.configuration.getValue(\"browser.zoomFactor\", 1.0)\n    }\n\n    private _initializeElement = (elem: HTMLElement) => {\n        if (elem && !this._webviewElement) {\n            const webviewElement = document.createElement(\"webview\")\n            webviewElement.preload = path.join(__dirname, \"lib\", \"webview_preload\", \"index.js\")\n            webviewElement.autosize = \"autosize\"\n            elem.appendChild(webviewElement)\n            this._webviewElement = webviewElement\n            this._navigate(this.props.initialUrl)\n\n            this._webviewElement.addEventListener(\"dom-ready\", () => {\n                this._webviewElement.setZoomFactor(this._getZoomFactor())\n            })\n\n            this._webviewElement.addEventListener(\"did-navigate\", (evt: any) => {\n                this.setState({\n                    url: evt.url,\n                })\n            })\n\n            this._webviewElement.addEventListener(\"focus\", () => {\n                focusManager.pushFocus(this._webviewElement)\n            })\n\n            this._webviewElement.addEventListener(\"blur\", () => {\n                focusManager.popFocus(this._webviewElement)\n            })\n\n            this._webviewElement.addEventListener(\"ipc-message\", event => {\n                switch (event.channel) {\n                    case \"focusin\":\n                        if (this.props.onFocusTag) {\n                            this.props.onFocusTag(event.args[0])\n                        }\n                        return\n                    case \"focusout\":\n                        if (this.props.onFocusTag) {\n                            this.props.onFocusTag(null)\n                        }\n                }\n            })\n\n            if (this.props.webviewRef) {\n                this.props.webviewRef(this._webviewElement)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Browser/index.tsx",
    "content": "/**\n * oni-layer-browser/index.ts\n *\n * Entry point for browser integration plugin\n */\n\nimport { shell, WebviewTag } from \"electron\"\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\nimport { Event } from \"oni-types\"\n\nimport { IBuffer } from \"./../../Editor/BufferManager\"\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { focusManager } from \"./../FocusManager\"\nimport {\n    AchievementsManager,\n    getInstance as getAchievementsInstance,\n} from \"./../Learning/Achievements\"\n\nimport { BrowserView } from \"./BrowserView\"\n\nexport class BrowserLayer implements Oni.BufferLayer {\n    private _debugEvent = new Event<void>()\n    private _goBackEvent = new Event<void>()\n    private _goForwardEvent = new Event<void>()\n    private _reloadEvent = new Event<void>()\n    private _scrollUpEvent = new Event<void>()\n    private _scrollDownEvent = new Event<void>()\n    private _scrollRightEvent = new Event<void>()\n    private _scrollLeftEvent = new Event<void>()\n\n    private _webview: WebviewTag | null = null\n    private _activeTagName: string | null = null\n\n    constructor(private _url: string, private _configuration: Configuration) {}\n\n    public get id(): string {\n        return \"oni.browser\"\n    }\n\n    public get webviewElement(): HTMLElement {\n        return this._webview\n    }\n\n    public get activeTagName(): string {\n        return this._activeTagName\n    }\n\n    public render(): JSX.Element {\n        return (\n            <BrowserView\n                configuration={this._configuration}\n                initialUrl={this._url}\n                goBack={this._goBackEvent}\n                goForward={this._goForwardEvent}\n                reload={this._reloadEvent}\n                debug={this._debugEvent}\n                scrollDown={this._scrollDownEvent}\n                scrollUp={this._scrollUpEvent}\n                scrollLeft={this._scrollLeftEvent}\n                scrollRight={this._scrollRightEvent}\n                webviewRef={webview => (this._webview = webview)}\n                onFocusTag={newTag => (this._activeTagName = newTag)}\n            />\n        )\n    }\n\n    public openDebugger(): void {\n        this._debugEvent.dispatch()\n    }\n\n    public goBack(): void {\n        this._goBackEvent.dispatch()\n    }\n\n    public goForward(): void {\n        this._goForwardEvent.dispatch()\n    }\n\n    public reload(): void {\n        this._reloadEvent.dispatch()\n    }\n\n    public scrollUp(): void {\n        this._scrollUpEvent.dispatch()\n    }\n\n    public scrollDown(): void {\n        this._scrollDownEvent.dispatch()\n    }\n\n    public scrollLeft(): void {\n        this._scrollLeftEvent.dispatch()\n    }\n\n    public scrollRight(): void {\n        this._scrollRightEvent.dispatch()\n    }\n}\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n) => {\n    let count = 0\n\n    const browserEnabledSetting = configuration.registerSetting(\"browser.enabled\", {\n        requiresReload: false,\n        description:\n            \"`browser.enabled` controls whether the embedded browser functionality is enabled\",\n        defaultValue: true,\n    })\n\n    configuration.registerSetting(\"browser.zoomFactor\", {\n        description: `This sets the \"zoomFactor\" for nested browser windows.\n        A value of \"1\" means \"100%\" zoom, a value of 0.5 means\n        \"50%\" zoom, and a value of \"2\" means \"200%\" zoom.`,\n        requiresReload: false,\n        defaultValue: 1,\n    })\n\n    const defaultUrlSetting = configuration.registerSetting(\"browser.defaultUrl\", {\n        description:\n            \"`browser.defaultUrl` sets the default url when opening a browser window, and no url was specified.\",\n        requiresReload: false,\n        defaultValue: \"https://github.com/onivim/oni\",\n    })\n\n    const openUrl = async (url: string, openMode: Oni.FileOpenMode = Oni.FileOpenMode.NewTab) => {\n        if (browserEnabledSetting.getValue()) {\n            url = url || defaultUrlSetting.getValue()\n\n            count++\n            const buffer: Oni.Buffer = await editorManager.activeEditor.openFile(\n                \"Browser\" + count.toString(),\n                { openMode },\n            )\n\n            const layer = new BrowserLayer(url, configuration)\n            buffer.addLayer(layer)\n\n            const achievements = getAchievementsInstance()\n            achievements.notifyGoal(\"oni.goal.openBrowser\")\n        } else {\n            shell.openExternal(url)\n        }\n    }\n\n    commandManager.registerCommand({\n        command: \"browser.openUrl.verticalSplit\",\n        name: \"Browser: Open in Vertical Split\",\n        detail: \"Open a browser window\",\n        execute: (url?: string) => openUrl(url, Oni.FileOpenMode.VerticalSplit),\n        enabled: () => browserEnabledSetting.getValue(),\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.openUrl.horizontalSplit\",\n        name: \"Browser: Open in Horizontal Split\",\n        detail: \"Open a browser window\",\n        execute: (url?: string) => openUrl(url, Oni.FileOpenMode.HorizontalSplit),\n        enabled: () => browserEnabledSetting.getValue(),\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.openUrl\",\n        execute: openUrl,\n        name: null,\n        detail: null,\n    })\n\n    commandManager.registerCommand({\n        command: \"oni.docs.open\",\n        execute: () => openUrl(\"https://onivim.github.io/oni-docs/#/\"),\n        name: \"Browser: Open Documentation\",\n        detail: \"Open Oni's Documentation website\",\n    })\n\n    const getLayerForBuffer = (buffer: Oni.Buffer): BrowserLayer => {\n        return (buffer as IBuffer).getLayerById<BrowserLayer>(\"oni.browser\")\n    }\n\n    const executeCommandForLayer = (callback: (browserLayer: BrowserLayer) => void) => () => {\n        const activeBuffer = editorManager.activeEditor.activeBuffer\n\n        const browserLayer = getLayerForBuffer(activeBuffer)\n        if (browserLayer) {\n            callback(browserLayer)\n        }\n    }\n\n    const isBrowserCommandEnabled = (): boolean => {\n        if (!browserEnabledSetting.getValue()) {\n            return false\n        }\n\n        const layer = getLayerForBuffer(editorManager.activeEditor.activeBuffer)\n        if (!layer) {\n            return false\n        }\n\n        // If the layer is open, but not focused, we shouldn't execute commands.\n        // This could happen if there is a pop-up menu, or if we're working with some\n        // non-webview UI in the browser (like the address bar)\n        if (layer.webviewElement !== focusManager.focusedElement) {\n            return false\n        }\n\n        return true\n    }\n\n    const isInputTag = (tagName: string): boolean => {\n        return tagName === \"INPUT\" || tagName === \"TEXTAREA\"\n    }\n\n    const isBrowserScrollCommandEnabled = (): boolean => {\n        if (!isBrowserCommandEnabled()) {\n            return false\n        }\n\n        const layer = getLayerForBuffer(editorManager.activeEditor.activeBuffer)\n\n        // Finally, if the webview _is_ focused, but something has focus, we'll\n        // skip our bindings and defer to the browser\n        if (isInputTag(layer.activeTagName)) {\n            return false\n        }\n\n        return true\n    }\n\n    // Per-layer commands\n    commandManager.registerCommand({\n        command: \"browser.debug\",\n        execute: executeCommandForLayer(browser => browser.openDebugger()),\n        name: \"Browser: Open DevTools\",\n        detail: \"Open the devtools pane for the current browser window.\",\n        enabled: isBrowserCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.goBack\",\n        execute: executeCommandForLayer(browser => browser.goBack()),\n        name: \"Browser: Go back\",\n        detail: \"\",\n        enabled: isBrowserCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.goForward\",\n        execute: executeCommandForLayer(browser => browser.goForward()),\n        name: \"Browser: Go forward\",\n        detail: \"\",\n        enabled: isBrowserCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.reload\",\n        execute: executeCommandForLayer(browser => browser.reload()),\n        name: \"Browser: Reload\",\n        detail: \"\",\n        enabled: isBrowserCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.scrollDown\",\n        execute: executeCommandForLayer(browser => browser.scrollDown()),\n        name: \"Browser: Scroll Down\",\n        detail: \"\",\n        enabled: isBrowserScrollCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.scrollUp\",\n        execute: executeCommandForLayer(browser => browser.scrollUp()),\n        name: \"Browser: Scroll Up\",\n        detail: \"\",\n        enabled: isBrowserScrollCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.scrollLeft\",\n        execute: executeCommandForLayer(browser => browser.scrollLeft()),\n        name: \"Browser: Scroll Left\",\n        detail: \"\",\n        enabled: isBrowserScrollCommandEnabled,\n    })\n\n    commandManager.registerCommand({\n        command: \"browser.scrollRight\",\n        execute: executeCommandForLayer(browser => browser.scrollRight()),\n        name: \"Browser: Scroll Right\",\n        detail: \"\",\n        enabled: isBrowserScrollCommandEnabled,\n    })\n}\n\nexport const registerAchievements = (achievements: AchievementsManager) => {\n    achievements.registerAchievement({\n        uniqueId: \"oni.achievement.openBrowser\",\n        name: \"Browserception\",\n        description: \"Open a browser window inside Oni\",\n        goals: [\n            {\n                name: null,\n                goalId: \"oni.goal.openBrowser\",\n                count: 1,\n            },\n        ],\n    })\n\n    achievements.registerAchievement({\n        uniqueId: \"oni.achievement.sneakIntoBrowser\",\n        name: \"Incognito\",\n        dependsOnId: \"oni.achievement.openBrowser\",\n        description: \"Use 'sneak' to interact with UI in the browser.\",\n        goals: [\n            {\n                name: null,\n                goalId: \"oni.goal.sneakIntoBrowser\",\n                count: 1,\n            },\n        ],\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/BrowserWindowConfigurationSynchronizer.ts",
    "content": "/**\n * BrowserWindowConfigurationSynchronizer\n *\n * Takes configuration settings, and applies them to the BrowserWindow\n */\n\nimport * as Color from \"color\"\nimport { ipcRenderer, remote } from \"electron\"\n\nimport { Colors } from \"./Colors\"\nimport { Configuration, IConfigurationValues } from \"./Configuration\"\n\nimport { addDefaultUnitIfNeeded } from \"./../Font\"\n\nexport const activate = (configuration: Configuration, colors: Colors) => {\n    const browserWindow = remote.getCurrentWindow()\n\n    let loadInitVim: boolean = false\n    const maximizeScreenOnStart: boolean = false\n\n    const onColorsChanged = () => {\n        // TODO: Read from 'persisted setting' instead\n        const backgroundColor = colors.getColor(\"background\")\n        if (backgroundColor) {\n            const background: string = Color(backgroundColor)\n                .lighten(0.1)\n                .hex()\n                .toString()\n            ;(browserWindow as any).setBackgroundColor(background)\n        }\n    }\n\n    colors.onColorsChanged.subscribe(() => onColorsChanged())\n\n    const onConfigChanged = (newConfigValues: Partial<IConfigurationValues>) => {\n        document.body.style.fontFamily = configuration.getValue(\"ui.fontFamily\")\n        document.body.style.fontSize = addDefaultUnitIfNeeded(configuration.getValue(\"ui.fontSize\"))\n        document.body.style.fontVariant = configuration.getValue(\"editor.fontLigatures\")\n            ? \"normal\"\n            : \"none\"\n\n        const fontSmoothing = configuration.getValue(\"ui.fontSmoothing\")\n\n        if (fontSmoothing) {\n            document.body.style[\"-webkit-font-smoothing\"] = fontSmoothing\n        }\n\n        const hideMenu: boolean | \"hidden\" = configuration.getValue(\"oni.hideMenu\")\n        if (hideMenu === \"hidden\") {\n            browserWindow.setMenu(null)\n        } else {\n            browserWindow.setAutoHideMenuBar(hideMenu)\n            browserWindow.setMenuBarVisibility(!hideMenu)\n        }\n\n        const loadInit: boolean = configuration.getValue(\"oni.loadInitVim\")\n        if (loadInit !== loadInitVim) {\n            ipcRenderer.send(\"rebuild-menu\", loadInit)\n            // don't rebuild menu unless oni.loadInitVim actually changed\n            loadInitVim = loadInit\n        }\n\n        const maximizeScreen: boolean = configuration.getValue(\"editor.maximizeScreenOnStart\")\n        if (maximizeScreen !== maximizeScreenOnStart) {\n            browserWindow.maximize()\n        }\n\n        browserWindow.setFullScreen(configuration.getValue(\"editor.fullScreenOnStart\"))\n    }\n\n    onConfigChanged(configuration.getValues())\n    configuration.onConfigurationChanged.subscribe(onConfigChanged)\n}\n"
  },
  {
    "path": "browser/src/Services/Colors.ts",
    "content": "/**\n * Colors\n *\n * - Rationalizes colors from both the active theme and configuration\n * - The 'source of truth' for colors in Oni\n * - Also will handle 'fallback logic' for colors\n */\n\nimport * as OniApi from \"oni-api\"\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { Configuration, IConfigurationValues } from \"./Configuration\"\nimport * as PersistentSettings from \"./Configuration/PersistentSettings\"\n\nimport { ThemeManager } from \"./Themes\"\n\nexport interface ColorsDictionary {\n    [colorName: string]: string\n}\n\nlet _colors: Colors = null\n\nexport const activate = (configuration: Configuration, themeManager: ThemeManager) => {\n    _colors = new Colors(configuration, themeManager)\n}\n\nexport const getInstance = (): Colors => {\n    return _colors\n}\n\nexport interface IColors extends OniApi.IColors {\n    onColorsChanged: IEvent<void>\n    getColors(): any\n}\n\nexport class Colors implements OniApi.IColors, IDisposable {\n    private _subscriptions: IDisposable[] = []\n    private _colors: ColorsDictionary = {}\n    private _onColorsChangedEvent: Event<void> = new Event<void>()\n\n    public get onColorsChanged(): IEvent<void> {\n        return this._onColorsChangedEvent\n    }\n\n    constructor(private _configuration: Configuration, private _themeManager: ThemeManager) {\n        const sub1 = this._themeManager.onThemeChanged.subscribe(() => {\n            this._updateColorsFromConfig()\n        })\n\n        const sub2 = this._configuration.onConfigurationChanged.subscribe(\n            (newValues: Partial<IConfigurationValues>) => {\n                const anyColorsChanged = Object.keys(newValues).filter(\n                    color => color.indexOf(\"colors.\") >= 0,\n                )\n\n                if (anyColorsChanged.length > 0) {\n                    this._updateColorsFromConfig()\n                }\n            },\n        )\n\n        this._subscriptions = [sub1, sub2]\n        this._updateColorsFromConfig()\n    }\n\n    public getColors(): ColorsDictionary {\n        return this._colors\n    }\n\n    public getColor(colorName: string): string | null {\n        return this._colors[colorName] || null\n    }\n\n    public dispose(): void {\n        if (this._subscriptions && this._subscriptions.length) {\n            this._subscriptions.forEach(disposable => disposable.dispose())\n            this._subscriptions = null\n        }\n    }\n\n    private _updateColorsFromConfig(): void {\n        if (!this._themeManager.activeTheme) {\n            return\n        }\n\n        const currentThemeColors = this._themeManager.getColors()\n        this._colors = {}\n\n        Object.keys(currentThemeColors).forEach(themeColor => {\n            const configurationName = this._getConfigurationNameForColor(themeColor)\n\n            const colorFromConfiguration = this._configuration.getValue(configurationName)\n\n            this._colors[themeColor] = colorFromConfiguration\n                ? colorFromConfiguration\n                : currentThemeColors[themeColor]\n        })\n\n        const lastBackgroundColor =\n            this._colors.background || this._colors[\"editor.background\"] || \"#1E2127\"\n        PersistentSettings.set(\"_internal.lastBackgroundColor\", lastBackgroundColor)\n\n        this._onColorsChangedEvent.dispatch()\n    }\n\n    private _getConfigurationNameForColor(colorName: string): string {\n        return \"colors.\" + colorName\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/CommandManager.ts",
    "content": "/**\n * CommandManager.ts\n *\n * Manages Oni commands. These commands show up in the command palette, and are exposed to plugins.\n */\n\nimport * as values from \"lodash/values\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { INeovimInstance } from \"./../neovim\"\nimport { ITask, ITaskProvider } from \"./Tasks\"\n\nexport class CallbackCommand implements Oni.Commands.ICommand {\n    public messageSuccess?: string\n    public messageFail?: string\n\n    constructor(\n        public command: string,\n        public name: string,\n        public detail: string,\n        public execute: Oni.Commands.CommandCallback,\n        public enabled?: Oni.Commands.CommandEnabledCallback,\n    ) {}\n}\n\nexport class VimCommand implements Oni.Commands.ICommand {\n    constructor(\n        public command: string,\n        public name: string,\n        public detail: string,\n        private _vimCommand: string,\n        private _neovimInstance: INeovimInstance,\n    ) {}\n\n    public execute(): void {\n        this._neovimInstance.command(this._vimCommand)\n    }\n}\n\nexport class CommandManager implements ITaskProvider {\n    private _commandDictionary: { [key: string]: Oni.Commands.ICommand } = {}\n\n    public clearCommands(): void {\n        this._commandDictionary = {}\n    }\n\n    // NOTE: Arrow function here preserves the \"this\" binding of this method\n    public registerCommand = (command: Oni.Commands.ICommand): void => {\n        if (this._commandDictionary[command.command]) {\n            Log.verbose(`Overwriting existing command: ${command.command}`)\n        }\n\n        this._commandDictionary[command.command] = command\n    }\n\n    public hasCommand(commandName: string): boolean {\n        return !!this._commandDictionary[commandName]\n    }\n\n    public unregisterCommand(commandName: string): void {\n        delete this._commandDictionary[commandName]\n    }\n\n    public executeCommand(name: string, args?: any): boolean | void {\n        const command = this._commandDictionary[name]\n\n        if (!command) {\n            return false\n        }\n\n        let enabled = true\n        if (typeof command.enabled === \"function\") {\n            enabled = command.enabled()\n        }\n\n        if (!enabled) {\n            return false\n        }\n\n        if (!command) {\n            Log.error(`Unable to find command: ${name}`)\n            return false\n        }\n\n        return command.execute(args)\n    }\n\n    public getTasks(): Promise<ITask[]> {\n        const commands = values(this._commandDictionary).filter(\n            (c: Oni.Commands.ICommand) => !c.enabled || c.enabled(),\n        )\n\n        const tasks = commands.map(c => ({\n            name: c.name,\n            detail: c.detail,\n            command: c.command,\n            messageSuccess: c.messageSuccess,\n            messageFail: c.messageFail,\n            callback: () => c.execute(),\n        }))\n\n        return Promise.resolve(tasks)\n    }\n}\n\nexport const commandManager = new CommandManager()\n"
  },
  {
    "path": "browser/src/Services/Commands/GlobalCommands.ts",
    "content": "/**\n * GlobalCommands.ts\n *\n * Built-in, general Oni commands, that are not specific\n * to an editor or service.\n */\n\nimport { remote } from \"electron\"\n\nimport * as Oni from \"oni-api\"\n\nimport { gotoNextError, gotoPreviousError } from \"./../../Services/Diagnostics/navigateErrors\"\nimport { EditorManager } from \"./../../Services/EditorManager\"\nimport { MenuManager } from \"./../../Services/Menu\"\nimport { showAboutMessage } from \"./../../Services/Metadata\"\nimport { multiProcess } from \"./../../Services/MultiProcess\"\nimport { Tasks } from \"./../../Services/Tasks\"\nimport { windowManager } from \"./../../Services/WindowManager\"\n\n// import * as UI from \"./../UI/index\"\n\nimport { CallbackCommand, CommandManager } from \"./../CommandManager\"\n\nimport * as Platform from \"./../../Platform\"\n\nexport const activate = (\n    commandManager: CommandManager,\n    editorManager: EditorManager,\n    menuManager: MenuManager,\n    tasks: Tasks,\n) => {\n    tasks.registerTaskProvider(commandManager)\n\n    const popupMenuCommand = (innerCommand: Oni.Commands.CommandCallback) => {\n        return () => {\n            if (menuManager.isMenuOpen()) {\n                return innerCommand()\n            }\n\n            return false\n        }\n    }\n\n    const popupMenuClose = popupMenuCommand(() => menuManager.closeActiveMenu())\n    const popupMenuNext = popupMenuCommand(() => menuManager.nextMenuItem())\n    const popupMenuPrevious = popupMenuCommand(() => menuManager.previousMenuItem())\n    const popupMenuSelect = popupMenuCommand(() => menuManager.selectMenuItem())\n\n    const commands = [\n        new CallbackCommand(\"editor.executeVimCommand\", null, null, (message: string) => {\n            const { neovim } = editorManager.activeEditor\n            if (message.startsWith(\":\")) {\n                neovim.command('exec \"' + message + '\"')\n            } else {\n                neovim.command('exec \":normal! ' + message + '\"')\n            }\n        }),\n        new CallbackCommand(\"oni.about\", null, null, () => showAboutMessage()),\n\n        new CallbackCommand(\"oni.process.openWindow\", \"New Window\", \"Open a new window\", () =>\n            multiProcess.openNewWindow(),\n        ),\n\n        new CallbackCommand(\"oni.editor.newFile\", \"Oni: Create new file\", \"Create a new file\", () =>\n            editorManager.activeEditor.neovim.command(\"enew!\"),\n        ),\n\n        new CallbackCommand(\n            \"oni.editor.maximize\",\n            \"Oni: Maximize Window\",\n            \"Maximize the current window\",\n            () => remote.getCurrentWindow().maximize(),\n        ),\n\n        new CallbackCommand(\n            \"oni.editor.minimize\",\n            \"Oni: Minimize Window\",\n            \"Minimize the current window\",\n            () => remote.getCurrentWindow().minimize(),\n        ),\n\n        new CallbackCommand(\"oni.editor.hide\", \"Hide Window\", \"Hide the current window\", () =>\n            remote.app.hide(),\n        ),\n\n        new CallbackCommand(\n            \"oni.process.cycleNext\",\n            \"Oni: Focus Next Oni\",\n            \"Switch to the next running instance of Oni\",\n            () => multiProcess.focusNextInstance(),\n        ),\n        new CallbackCommand(\n            \"oni.process.cyclePrevious\",\n            \"Oni: Focus Previous Oni\",\n            \"Switch to the previous running instance of Oni\",\n            () => multiProcess.focusPreviousInstance(),\n        ),\n\n        new CallbackCommand(\"commands.show\", null, null, () => tasks.show()),\n\n        // Autocompletion\n        // Menu\n        new CallbackCommand(\"menu.close\", null, null, popupMenuClose),\n        new CallbackCommand(\"menu.next\", null, null, popupMenuNext),\n        new CallbackCommand(\"menu.previous\", null, null, popupMenuPrevious),\n        new CallbackCommand(\"menu.select\", null, null, popupMenuSelect),\n\n        // QuickOpen\n        new CallbackCommand(\"window.moveLeft\", null, null, () => windowManager.moveLeft()),\n        new CallbackCommand(\"window.moveRight\", null, null, () => windowManager.moveRight()),\n        new CallbackCommand(\"window.moveDown\", null, null, () => windowManager.moveDown()),\n        new CallbackCommand(\"window.moveUp\", null, null, () => windowManager.moveUp()),\n\n        // Error list\n        new CallbackCommand(\n            \"oni.editor.nextError\",\n            \"Jump to next lint/compiler error\",\n            \"Jump to the next error or warning from the linter or compiler\",\n            gotoNextError,\n        ),\n        new CallbackCommand(\n            \"oni.editor.previousError\",\n            \"Jump to previous lint/compiler error\",\n            \"Jump to the previous error or warning from the linter or compiler\",\n            gotoPreviousError,\n        ),\n\n        // Add additional commands here\n        // ...\n    ]\n\n    // TODO: once implementations of this command work on all platforms, remove the exclusive check for OSX\n    if (Platform.isMac()) {\n        const addToPathCommand = new CallbackCommand(\n            \"oni.editor.removeFromPath\",\n            \"Oni: Remove from PATH\",\n            \"Disable executing 'oni' from terminal\",\n            Platform.removeFromPath,\n            () => Platform.isAddedToPath(),\n        )\n        addToPathCommand.messageSuccess = \"Oni has been removed from the $PATH\"\n\n        const removeFromPathCommand = new CallbackCommand(\n            \"oni.editor.addToPath\",\n            \"Oni: Add to PATH\",\n            \"Enable executing 'oni' from terminal\",\n            Platform.addToPath,\n            () => !Platform.isAddedToPath(),\n        )\n        removeFromPathCommand.messageSuccess = \"Oni has been added to the $PATH\"\n\n        commands.push(addToPathCommand)\n        commands.push(removeFromPathCommand)\n    }\n\n    commands.forEach(c => commandManager.registerCommand(c))\n}\n"
  },
  {
    "path": "browser/src/Services/Commands/index.ts",
    "content": "export * from \"./GlobalCommands\"\n"
  },
  {
    "path": "browser/src/Services/Completion/Completion.ts",
    "content": "/**\n * Completion.ts\n */\n\nimport * as Oni from \"oni-api\"\nimport { Event, IDisposable, IEvent } from \"oni-types\"\nimport { Store, Unsubscribe } from \"redux\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { LanguageManager } from \"./../Language\"\nimport { SnippetManager } from \"./../Snippets\"\nimport { ISyntaxHighlighter } from \"./../SyntaxHighlighting\"\n\nimport { getFilteredCompletions } from \"./CompletionSelectors\"\nimport { ICompletionsRequestor } from \"./CompletionsRequestor\"\n\nimport { ICompletionState } from \"./CompletionState\"\n\nimport { createStore } from \"./CompletionStore\"\n\nimport { Configuration } from \"./../Configuration\"\n\nexport interface ICompletionShowEventArgs {\n    filteredCompletions: types.CompletionItem[]\n    base: string\n}\n\nexport class Completion implements IDisposable {\n    private _lastCursorPosition: Oni.Cursor\n    private _store: Store<ICompletionState>\n    private _storeUnsubscribe: Unsubscribe = null\n    private _subscriptions: IDisposable[]\n\n    private _onShowCompletionItemsEvent: Event<ICompletionShowEventArgs> = new Event<\n        ICompletionShowEventArgs\n    >()\n    private _onHideCompletionItemsEvent: Event<void> = new Event<void>()\n\n    public get onShowCompletionItems(): IEvent<ICompletionShowEventArgs> {\n        return this._onShowCompletionItemsEvent\n    }\n\n    public get onHideCompletionItems(): IEvent<void> {\n        return this._onHideCompletionItemsEvent\n    }\n\n    constructor(\n        private _editor: Oni.Editor,\n        private _configuration: Configuration,\n        private _completionsRequestor: ICompletionsRequestor,\n        private _languageManager: LanguageManager,\n        private _snippetManager: SnippetManager,\n        private _syntaxHighlighter: ISyntaxHighlighter,\n    ) {\n        this._completionsRequestor = this._completionsRequestor\n        this._store = createStore(\n            this._editor,\n            this._languageManager,\n            this._configuration,\n            this._completionsRequestor,\n            this._snippetManager,\n            this._syntaxHighlighter,\n        )\n\n        const sub1 = this._editor.onBufferEnter.subscribe((buf: Oni.Buffer) => {\n            this._onBufferEnter(buf)\n        })\n\n        const sub2 = this._editor.onBufferChanged.subscribe(\n            (buf: Oni.EditorBufferChangedEventArgs) => {\n                this._onBufferUpdate(buf)\n            },\n        )\n\n        const sub3 = this._editor.onModeChanged.subscribe((newMode: string) => {\n            this._onModeChanged(newMode)\n        })\n\n        const sub4 = this._editor.onCursorMoved.subscribe((cursor: Oni.Cursor) => {\n            this._onCursorMoved(cursor)\n        })\n\n        this._subscriptions = [sub1, sub2, sub3, sub4]\n        this._storeUnsubscribe = this._store.subscribe(() =>\n            this._onStateChanged(this._store.getState()),\n        )\n    }\n\n    public resolveItem(completionItem: types.CompletionItem): void {\n        this._store.dispatch({\n            type: \"GET_COMPLETION_ITEM_DETAILS\",\n            completionItem,\n        })\n    }\n\n    public commitItem(completionItem: types.CompletionItem): void {\n        const state = this._store.getState()\n        this._store.dispatch({\n            type: \"COMMIT_COMPLETION\",\n            meetLine: state.meetInfo.meetLine,\n            meetPosition: state.meetInfo.meetPosition,\n            completion: completionItem,\n        })\n    }\n\n    public dispose(): void {\n        if (this._subscriptions) {\n            this._subscriptions.forEach(disposable => disposable.dispose())\n            this._subscriptions = null\n        }\n\n        if (this._storeUnsubscribe) {\n            this._storeUnsubscribe()\n            this._storeUnsubscribe = null\n        }\n    }\n\n    private _onStateChanged(newState: ICompletionState): void {\n        const filteredCompletions = getFilteredCompletions(newState)\n\n        if (filteredCompletions && filteredCompletions.length) {\n            this._onShowCompletionItemsEvent.dispatch({\n                filteredCompletions,\n                base: newState.meetInfo.meetBase,\n            })\n        } else {\n            this._onHideCompletionItemsEvent.dispatch()\n        }\n    }\n\n    private _onCursorMoved(cursor: Oni.Cursor): void {\n        this._lastCursorPosition = cursor\n    }\n\n    private _onBufferEnter(buffer: Oni.Buffer): void {\n        this._store.dispatch({\n            type: \"BUFFER_ENTER\",\n            language: buffer.language,\n            filePath: buffer.filePath,\n            bufferId: buffer.id,\n        })\n    }\n\n    private _onBufferUpdate(bufferUpdate: Oni.EditorBufferChangedEventArgs): void {\n        // Ignore if this is a full update\n        const firstChange = bufferUpdate.contentChanges[0]\n\n        if (!firstChange || !firstChange.range) {\n            return\n        }\n\n        const range = firstChange.range\n\n        // We only work with single line changes, for now.\n        // Perhaps we could get the latest line by querying the activeBuffer\n        // from cursorMoved, but right now, the update comes _after_\n        // the cursorMoved event - so this is the most reliable way.\n        if (range.start.line + 1 !== range.end.line) {\n            return\n        }\n\n        const newLine = firstChange.text\n\n        if (this._lastCursorPosition && range.start.line === this._lastCursorPosition.line) {\n            this._store.dispatch({\n                type: \"CURSOR_MOVED\",\n                line: this._lastCursorPosition.line,\n                column: this._lastCursorPosition.column,\n                lineContents: newLine,\n            })\n        }\n    }\n\n    private async _onModeChanged(newMode: string): Promise<void> {\n        if (newMode === \"insert\" && this._lastCursorPosition) {\n            const [latestLine] = await this._editor.activeBuffer.getLines(\n                this._lastCursorPosition.line,\n                this._lastCursorPosition.line + 1,\n            )\n\n            this._store.dispatch({\n                type: \"CURSOR_MOVED\",\n                line: this._lastCursorPosition.line,\n                column: this._lastCursorPosition.column,\n                lineContents: latestLine,\n            })\n        }\n\n        this._store.dispatch({\n            type: \"MODE_CHANGED\",\n            mode: newMode,\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/CompletionProviders.ts",
    "content": "/**\n * CompletionProviders.ts\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { LanguageManager } from \"./../Language\"\n\nimport {\n    CompletionsRequestContext,\n    ICompletionsRequestor,\n    LanguageServiceCompletionsRequestor,\n} from \"./CompletionsRequestor\"\n\nexport interface ICompletionProviderInfo {\n    id: string\n    provider: ICompletionsRequestor\n}\n\nexport interface ICompletionInfoWithProvider extends types.CompletionItem {\n    __provider: string\n}\n\nexport class CompletionProviders implements ICompletionsRequestor {\n    private _completionProviders: ICompletionProviderInfo[] = []\n\n    public registerCompletionProvider(id: string, provider: ICompletionsRequestor): void {\n        this._completionProviders.push({\n            id,\n            provider,\n        })\n    }\n\n    public async getCompletions(\n        context: CompletionsRequestContext,\n    ): Promise<types.CompletionItem[]> {\n        const completionItemsPromise = this._completionProviders.map(async prov => {\n            const items = (await prov.provider.getCompletions(context)) || []\n\n            // Tag the items with the provider id, so we know who to ask for details\n            const augmentedItems = items.map(item => {\n                return {\n                    ...item,\n                    __provider: prov.id,\n                }\n            })\n\n            return augmentedItems\n        })\n\n        const allItems = await Promise.all(completionItemsPromise)\n\n        const flattenedItems = allItems.reduce(\n            (prev: ICompletionInfoWithProvider[], current: ICompletionInfoWithProvider[]) => {\n                return [...prev, ...current]\n            },\n            [] as ICompletionInfoWithProvider[],\n        )\n\n        return flattenedItems\n    }\n\n    public async getCompletionDetails(\n        language: string,\n        filePath: string,\n        completionItem: ICompletionInfoWithProvider,\n    ): Promise<types.CompletionItem> {\n        if (completionItem && completionItem.__provider) {\n            const prov = this._getProviderById(completionItem.__provider)\n\n            if (prov && prov.getCompletionDetails) {\n                return prov.getCompletionDetails(language, filePath, completionItem)\n            }\n        }\n\n        return completionItem\n    }\n\n    private _getProviderById(id: string): ICompletionsRequestor {\n        const providersMatchingId = this._completionProviders.filter(prov => prov.id === id)\n\n        return providersMatchingId.length > 0 ? providersMatchingId[0].provider : null\n    }\n}\n\nlet _completionProviders: CompletionProviders\n\nexport const activate = (languageManager: LanguageManager) => {\n    _completionProviders = new CompletionProviders()\n\n    const languageServiceCompletion = new LanguageServiceCompletionsRequestor(languageManager)\n\n    _completionProviders.registerCompletionProvider(\n        \"oni.completions.language-server\",\n        languageServiceCompletion,\n    )\n}\n\nexport const getInstance = (): CompletionProviders => {\n    return _completionProviders\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/CompletionSelectors.ts",
    "content": "/**\n * CompletionSelectors.ts\n *\n * Selectors are functions that take a state and derive a value from it.\n */\nimport * as isEqual from \"lodash/isEqual\"\nimport * as omit from \"lodash/omit\"\n\nimport { ICompletionState } from \"./CompletionState\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nconst EmptyCompletions: types.CompletionItem[] = []\n\nimport * as CompletionUtility from \"./CompletionUtility\"\n\nexport const getFilteredCompletions = (state: ICompletionState): types.CompletionItem[] => {\n    if (!state.completionResults.completions || !state.completionResults.completions.length) {\n        return EmptyCompletions\n    }\n\n    if (!state.meetInfo.shouldExpand) {\n        return EmptyCompletions\n    }\n\n    // If the completions were for a different meet line/position, we probably\n    // shouldn't show them...\n    if (\n        state.meetInfo.meetLine !== state.completionResults.meetLine ||\n        state.meetInfo.meetPosition !== state.completionResults.meetPosition\n    ) {\n        return EmptyCompletions\n    }\n\n    // If we had previously accepted this completion, don't show it either\n    if (\n        state.meetInfo.meetLine === state.lastCompletionInfo.meetLine &&\n        state.meetInfo.meetPosition === state.lastCompletionInfo.meetPosition &&\n        state.meetInfo.meetBase ===\n            CompletionUtility.getInsertText(state.lastCompletionInfo.completion)\n    ) {\n        return EmptyCompletions\n    }\n\n    const completions = state.completionResults.completions\n\n    const filteredCompletions = filterCompletionOptions(completions, state.meetInfo.meetBase)\n\n    if (!filteredCompletions || !filteredCompletions.length) {\n        return EmptyCompletions\n    }\n\n    // If there is only one element, and it matches our base,\n    // don't bother showing it..\n    if (\n        CompletionUtility.getInsertText(filteredCompletions[0]) === state.meetInfo.meetBase &&\n        filteredCompletions.length === 1\n    ) {\n        return EmptyCompletions\n    }\n\n    return filteredCompletions\n}\n\nexport const filterCompletionOptions = (\n    items: types.CompletionItem[],\n    searchText: string,\n): types.CompletionItem[] => {\n    if (!searchText) {\n        return items\n    }\n    if (!items || !items.length) {\n        return null\n    }\n\n    // Must start with first letter in searchText, and then be at least abbreviated by searchText.\n    const filterRegEx = new RegExp(\"^\" + searchText.split(\"\").join(\".*\") + \".*\")\n    const filteredOptions = items.filter(f => {\n        const textToFilterOn = f.filterText || f.label\n        return textToFilterOn.match(filterRegEx)\n    })\n    const sortedOptions = filteredOptions.sort((itemA, itemB) => {\n        const itemASortText = itemA.filterText || itemA.label\n        const itemBSortText = itemB.filterText || itemB.label\n\n        const indexOfA = itemASortText.indexOf(searchText)\n        const indexOfB = itemBSortText.indexOf(searchText)\n\n        // Ensure abbreviated matches are sorted below exact matches.\n        if (indexOfA >= 0 && indexOfB === -1) {\n            return -1\n        } else if (indexOfA === -1 && indexOfB >= 0) {\n            return 1\n            // Else sort by label to keep related results together.\n        } else if (itemASortText < itemBSortText) {\n            return -1\n        } else if (itemASortText > itemBSortText) {\n            return 1\n            // Fallback to sort by language server specified sortText.\n        } else if (itemA.sortText < itemB.sortText) {\n            return -1\n        } else if (itemA.sortText > itemB.sortText) {\n            return 1\n        }\n        return 0\n    })\n    // Language servers can return duplicate entries (e.g. cquery).\n    const uniqueOptions: types.CompletionItem[] = _uniq(sortedOptions)\n\n    return uniqueOptions\n}\n\n/**\n * Get unique completion items, assuming they're sorted so duplicates are contiguous.\n *\n * Adapted from https://github.com/lodash/lodash/blob/master/.internal/baseSortedUniq.js, since\n * lodash has no `sortedUniqWith` function.\n */\nconst _uniq = (array: types.CompletionItem[]) => {\n    let seenReduced: any\n    let index = -1\n    let resIndex = 0\n\n    const { length } = array\n    const result = []\n\n    while (++index < length) {\n        const value = array[index]\n        // Omit the `sortText` which can be different even if all other attributes are the same.\n        const reduced = omit(value, \"sortText\")\n        if (!index || !isEqual(reduced, seenReduced)) {\n            seenReduced = reduced\n            result[resIndex++] = value\n        }\n    }\n    return result\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/CompletionState.ts",
    "content": "/**\n * CompletionStore.ts\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nexport interface ICompletionState {\n    enabled: boolean\n    cursorInfo: ICursorInfo\n    bufferInfo: ICompletionBufferInfo\n    meetInfo: ICompletionMeetInfo\n    completionResults: ICompletionResults\n    lastCompletionInfo: ILastCompletionInfo\n}\n\nexport interface ICompletionMeetInfo {\n    meetLine: number\n    meetPosition: number\n    queryPosition: number\n    meetBase: string\n    shouldExpand: boolean\n    textMateScopes: string[]\n}\n\nexport const DefaultMeetInfo: ICompletionMeetInfo = {\n    meetLine: -1,\n    meetPosition: -1,\n    queryPosition: -1,\n    meetBase: \"\",\n    shouldExpand: false,\n    textMateScopes: [],\n}\n\nexport interface ICompletionBufferInfo {\n    language: string\n    filePath: string\n    bufferId: string\n}\n\nexport const DefaultCompletionBufferInfo: ICompletionBufferInfo = {\n    language: null,\n    filePath: null,\n    bufferId: null,\n}\n\nexport interface ILastCompletionInfo {\n    meetLine: number\n    meetPosition: number\n    completion: types.CompletionItem\n}\n\nexport const DefaultLastCompletionInfo: ILastCompletionInfo = {\n    meetLine: -1,\n    meetPosition: -1,\n    completion: null,\n}\n\nexport interface ICompletionResults {\n    completions: types.CompletionItem[]\n    meetLine: number\n    meetPosition: number\n}\n\nexport const DefaultCompletionResults: ICompletionResults = {\n    completions: [],\n    meetLine: -1,\n    meetPosition: -1,\n}\n\nexport interface ICursorInfo {\n    line: number\n    column: number\n    lineContents: string\n}\n\nexport const DefaultCursorInfo: ICursorInfo = {\n    line: -1,\n    column: -1,\n    lineContents: \"\",\n}\n\nexport const DefaultCompletionState: ICompletionState = {\n    enabled: false,\n    cursorInfo: DefaultCursorInfo,\n    bufferInfo: DefaultCompletionBufferInfo,\n    meetInfo: DefaultMeetInfo,\n    completionResults: DefaultCompletionResults,\n    lastCompletionInfo: DefaultLastCompletionInfo,\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/CompletionStore.ts",
    "content": "/**\n * CompletionStore.ts\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport \"rxjs/add/operator/mergeMap\"\nimport { Observable } from \"rxjs/Observable\"\n\nimport { combineReducers, Reducer, Store } from \"redux\"\nimport { combineEpics, createEpicMiddleware, Epic } from \"redux-observable\"\n\nimport { createStore as oniCreateStore } from \"./../../Redux\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { LanguageManager } from \"./../Language\"\nimport { SnippetManager } from \"./../Snippets\"\nimport { ISyntaxHighlighter } from \"./../SyntaxHighlighting\"\n\nimport * as CompletionSelects from \"./CompletionSelectors\"\nimport { ICompletionsRequestor } from \"./CompletionsRequestor\"\nimport * as CompletionUtility from \"./CompletionUtility\"\n\nimport {\n    DefaultCompletionResults,\n    DefaultCompletionState,\n    DefaultCursorInfo,\n    DefaultLastCompletionInfo,\n    DefaultMeetInfo,\n    ICompletionBufferInfo,\n    ICompletionMeetInfo,\n    ICompletionResults,\n    ICompletionState,\n    ICursorInfo,\n    ILastCompletionInfo,\n} from \"./CompletionState\"\n\nexport type CompletionAction =\n    | {\n          type: \"CURSOR_MOVED\"\n          line: number\n          column: number\n          lineContents: string\n      }\n    | {\n          type: \"MODE_CHANGED\"\n          mode: string\n      }\n    | {\n          type: \"BUFFER_ENTER\"\n          language: string\n          filePath: string\n          bufferId: string\n      }\n    | {\n          type: \"COMMIT_COMPLETION\"\n          meetBase: string\n          meetLine: number\n          meetPosition: number\n          completion: types.CompletionItem\n      }\n    | {\n          type: \"MEET_CHANGED\"\n          currentMeet: ICompletionMeetInfo\n      }\n    | {\n          type: \"GET_COMPLETIONS_RESULT\"\n          meetLine: number\n          meetPosition: number\n          completions: types.CompletionItem[]\n      }\n    | {\n          type: \"GET_COMPLETION_ITEM_DETAILS\"\n          completionItem: types.CompletionItem\n      }\n    | {\n          type: \"GET_COMPLETION_ITEM_DETAILS_RESULT\"\n          completionItemWithDetails: types.CompletionItem\n      }\n\nconst bufferInfoReducer: Reducer<ICompletionBufferInfo> = (\n    state: ICompletionBufferInfo = {\n        language: null,\n        filePath: null,\n        bufferId: null,\n    },\n    action: CompletionAction,\n) => {\n    switch (action.type) {\n        case \"BUFFER_ENTER\":\n            return {\n                language: action.language,\n                filePath: action.filePath,\n                bufferId: action.bufferId,\n            }\n        default:\n            return state\n    }\n}\n\nconst meetInfoReducer: Reducer<ICompletionMeetInfo> = (\n    state: ICompletionMeetInfo = DefaultMeetInfo,\n    action: CompletionAction,\n) => {\n    switch (action.type) {\n        case \"MODE_CHANGED\":\n            return DefaultMeetInfo\n        case \"MEET_CHANGED\":\n            return {\n                ...action.currentMeet,\n            }\n        default:\n            return state\n    }\n}\n\nexport const completionResultsReducer: Reducer<ICompletionResults> = (\n    state: ICompletionResults = DefaultCompletionResults,\n    action: CompletionAction,\n) => {\n    switch (action.type) {\n        case \"MODE_CHANGED\":\n        case \"BUFFER_ENTER\":\n            return DefaultCompletionResults\n        case \"GET_COMPLETIONS_RESULT\":\n            return {\n                meetLine: action.meetLine,\n                meetPosition: action.meetPosition,\n                completions: action.completions,\n            }\n        case \"GET_COMPLETION_ITEM_DETAILS_RESULT\":\n            return {\n                ...state,\n                completions: state.completions.map(completion => {\n                    // Prefer `detail` field if available, to avoid splatting e.g. methods with\n                    // the same name but different signature.\n                    if (completion.detail && action.completionItemWithDetails.detail) {\n                        if (completion.detail === action.completionItemWithDetails.detail) {\n                            return action.completionItemWithDetails\n                        } else {\n                            return completion\n                        }\n                    }\n\n                    if (completion.label === action.completionItemWithDetails.label) {\n                        return action.completionItemWithDetails\n                    } else {\n                        return completion\n                    }\n                }),\n            }\n        default:\n            return state\n    }\n}\n\nexport const cursorInfoReducer: Reducer<ICursorInfo> = (\n    state: ICursorInfo = DefaultCursorInfo,\n    action: CompletionAction,\n) => {\n    switch (action.type) {\n        case \"CURSOR_MOVED\":\n            return {\n                line: action.line,\n                lineContents: action.lineContents,\n                column: action.column,\n            }\n        default:\n            return state\n    }\n}\n\nexport const enabledReducer: Reducer<boolean> = (\n    state: boolean = false,\n    action: CompletionAction,\n) => {\n    switch (action.type) {\n        case \"MODE_CHANGED\":\n            return action.mode === \"insert\"\n        default:\n            return state\n    }\n}\n\nexport const lastCompletionInfoReducer: Reducer<ILastCompletionInfo> = (\n    state: ILastCompletionInfo = DefaultLastCompletionInfo,\n    action: CompletionAction,\n) => {\n    switch (action.type) {\n        case \"MODE_CHANGED\":\n        case \"BUFFER_ENTER\":\n            return DefaultLastCompletionInfo\n        case \"COMMIT_COMPLETION\":\n            return {\n                meetLine: action.meetLine,\n                meetPosition: action.meetPosition,\n                completion: action.completion,\n            }\n        default:\n            return state\n    }\n}\n\nconst nullAction: CompletionAction = { type: null } as CompletionAction\n\nconst createGetCompletionMeetEpic = (\n    languageManager: LanguageManager,\n    configuration: Configuration,\n    syntaxHighlighter: ISyntaxHighlighter,\n): Epic<CompletionAction, ICompletionState> => (action$, store) =>\n    action$\n        .ofType(\"CURSOR_MOVED\")\n        .filter(\n            () =>\n                configuration.getValue(\"editor.completions.mode\") === \"oni\" &&\n                configuration.getValue(\"editor.completions.enabled\") !== false,\n        )\n        .auditTime(10)\n        .map((action: CompletionAction) => {\n            const currentState: ICompletionState = store.getState()\n\n            if (!currentState.enabled) {\n                return nullAction\n            }\n\n            if (!currentState.bufferInfo || !currentState.bufferInfo.language) {\n                return nullAction\n            }\n\n            if (!currentState.cursorInfo || !currentState.cursorInfo.lineContents) {\n                return nullAction\n            }\n\n            const { bufferInfo } = currentState\n\n            const token = languageManager.getTokenRegex(bufferInfo.language)\n            const completionCharacters = languageManager.getCompletionTriggerCharacters(\n                bufferInfo.language,\n            )\n\n            const meet = CompletionUtility.getCompletionMeet(\n                currentState.cursorInfo.lineContents,\n                currentState.cursorInfo.column,\n                token,\n                completionCharacters,\n            )\n\n            const highlightInfo = syntaxHighlighter.getHighlightTokenAt(\n                currentState.bufferInfo.bufferId,\n                types.Position.create(currentState.cursorInfo.line, meet.positionToQuery),\n            )\n            const scopes = highlightInfo && highlightInfo.scopes ? highlightInfo.scopes : []\n\n            const meetForAction: ICompletionMeetInfo = {\n                meetPosition: meet.position,\n                meetLine: currentState.cursorInfo.line,\n                queryPosition: meet.positionToQuery,\n                meetBase: meet.base,\n                shouldExpand: meet.shouldExpandCompletions,\n                textMateScopes: scopes,\n            }\n\n            return {\n                type: \"MEET_CHANGED\",\n                currentMeet: meetForAction,\n            } as CompletionAction\n        })\n\nconst commitCompletionEpic = (\n    editor: Oni.Editor,\n    snippetManager: SnippetManager,\n): Epic<CompletionAction, ICompletionState> => (action$, store) =>\n    action$\n        .ofType(\"COMMIT_COMPLETION\")\n        .do(async (action: CompletionAction) => {\n            if (action.type !== \"COMMIT_COMPLETION\") {\n                return\n            }\n\n            await CompletionUtility.commitCompletion(\n                editor.activeBuffer,\n                action.meetLine,\n                action.meetPosition,\n                action.completion,\n                snippetManager,\n            )\n        })\n        .map(_ => nullAction)\n\nconst createGetCompletionsEpic = (\n    completionsRequestor: ICompletionsRequestor,\n): Epic<CompletionAction, ICompletionState> => (action$, store) =>\n    action$\n        .ofType(\"MEET_CHANGED\")\n        .filter(() => store.getState().enabled)\n        .filter(action => {\n            const state = store.getState()\n\n            if (action.type !== \"MEET_CHANGED\") {\n                return false\n            }\n\n            if (!action.currentMeet.shouldExpand) {\n                return false\n            }\n\n            if (\n                action.currentMeet.meetLine === state.completionResults.meetLine &&\n                action.currentMeet.meetPosition === state.completionResults.meetPosition\n            ) {\n                return false\n            }\n\n            return true\n        })\n        .switchMap((action: CompletionAction): Observable<CompletionAction> => {\n            const state = store.getState()\n\n            // Helper to let TypeScript know that we can assume this is 'MEET_CHANGED'...\n            if (action.type !== \"MEET_CHANGED\") {\n                return Observable.of(nullAction)\n            }\n\n            if (!state.enabled) {\n                return Observable.of(nullAction)\n            }\n\n            // Check if the meet is different from the last meet we queried\n            const requestResult: Observable<types.CompletionItem[]> = Observable.defer(async () => {\n                const results = await completionsRequestor.getCompletions({\n                    language: state.bufferInfo.language,\n                    filePath: state.bufferInfo.filePath,\n                    line: action.currentMeet.meetLine,\n                    column: action.currentMeet.queryPosition,\n                    meetCharacter: action.currentMeet.meetBase,\n                    textMateScopes: action.currentMeet.textMateScopes,\n                })\n                const completions = results || []\n                const orderedCompletions = orderCompletions(\n                    completions,\n                    action.currentMeet.meetBase,\n                )\n                return orderedCompletions\n            })\n\n            const ret = requestResult.map(completions => {\n                return {\n                    type: \"GET_COMPLETIONS_RESULT\",\n                    meetLine: action.currentMeet.meetLine,\n                    meetPosition: action.currentMeet.meetPosition,\n                    completions,\n                } as CompletionAction\n            })\n\n            return ret\n        })\n\nexport const orderCompletions = (\n    completions: types.CompletionItem[],\n    base: string,\n): types.CompletionItem[] => {\n    if (!completions || !completions.length) {\n        return completions\n    }\n\n    const anyCompletionsMatchCurrentBase = completions.find(\n        item => CompletionUtility.getInsertText(item) === base,\n    )\n\n    if (!anyCompletionsMatchCurrentBase) {\n        return completions\n    }\n\n    const filteredCompletions = completions.filter(item => item !== anyCompletionsMatchCurrentBase)\n\n    const ret = [anyCompletionsMatchCurrentBase, ...filteredCompletions]\n    return ret\n}\n\nconst createGetCompletionDetailsEpic = (\n    completionsRequestor: ICompletionsRequestor,\n): Epic<CompletionAction, ICompletionState> => (action$, store) =>\n    action$.ofType(\"GET_COMPLETION_ITEM_DETAILS\").switchMap(action => {\n        if (action.type !== \"GET_COMPLETION_ITEM_DETAILS\") {\n            return Observable.of(nullAction)\n        }\n\n        return Observable.defer(async () => {\n            const state = store.getState()\n\n            const result = await completionsRequestor.getCompletionDetails(\n                state.bufferInfo.language,\n                state.bufferInfo.filePath,\n                action.completionItem,\n            )\n            return result\n        }).map((itemResult: types.CompletionItem) => {\n            if (itemResult) {\n                return {\n                    type: \"GET_COMPLETION_ITEM_DETAILS_RESULT\",\n                    completionItemWithDetails: itemResult,\n                } as CompletionAction\n            } else {\n                return nullAction\n            }\n        })\n    })\n\nconst selectFirstItemEpic: Epic<CompletionAction, ICompletionState> = (action$, store) =>\n    action$.ofType(\"GET_COMPLETIONS_RESULT\").map(action => {\n        if (action.type !== \"GET_COMPLETIONS_RESULT\") {\n            return nullAction\n        }\n\n        const state = store.getState()\n        const filteredItems = CompletionSelects.filterCompletionOptions(\n            action.completions,\n            state.meetInfo.meetBase,\n        )\n\n        if (!filteredItems || !filteredItems.length) {\n            return nullAction\n        }\n\n        return {\n            type: \"GET_COMPLETION_ITEM_DETAILS\",\n            completionItem: filteredItems[0],\n        } as CompletionAction\n    })\n\nexport const createStore = (\n    editor: Oni.Editor,\n    languageManager: LanguageManager,\n    configuration: Configuration,\n    completionsRequestor: ICompletionsRequestor,\n    snippetManager: SnippetManager,\n    syntaxHighlighter: ISyntaxHighlighter,\n): Store<ICompletionState> => {\n    return oniCreateStore(\n        \"COMPLETION_STORE\",\n        combineReducers<ICompletionState>({\n            enabled: enabledReducer,\n            bufferInfo: bufferInfoReducer,\n            meetInfo: meetInfoReducer,\n            completionResults: completionResultsReducer,\n            lastCompletionInfo: lastCompletionInfoReducer,\n            cursorInfo: cursorInfoReducer,\n        }),\n        DefaultCompletionState,\n        [\n            createEpicMiddleware(\n                combineEpics(\n                    commitCompletionEpic(editor, snippetManager),\n                    createGetCompletionMeetEpic(languageManager, configuration, syntaxHighlighter),\n                    createGetCompletionsEpic(completionsRequestor),\n                    createGetCompletionDetailsEpic(completionsRequestor),\n                    selectFirstItemEpic,\n                ),\n            ),\n        ],\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/CompletionUtility.ts",
    "content": "/**\n * CompletionUtility.ts\n *\n * Helper functions for auto completion\n */\n\nimport * as Oni from \"oni-api\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { SnippetManager } from \"./../Snippets\"\n\nexport const commitCompletion = async (\n    buffer: Oni.Buffer,\n    line: number,\n    base: number,\n    completion: types.CompletionItem,\n    snippetManager?: SnippetManager,\n) => {\n    const currentLines = await buffer.getLines(line, line + 1)\n\n    const column = buffer.cursor.column\n\n    if (!currentLines || !currentLines.length) {\n        return\n    }\n\n    const originalLine = currentLines[0]\n\n    const isSnippet =\n        completion.insertTextFormat === types.InsertTextFormat.Snippet && snippetManager\n\n    // If it's a snippet, we don't insert any text - we'll let the insert manager handle that.\n    const textToReplace = isSnippet ? \"\" : getInsertText(completion)\n\n    const newLine = replacePrefixWithCompletion(originalLine, base, column, textToReplace)\n    await buffer.setLines(line, line + 1, [newLine])\n    const cursorOffset = newLine.length - originalLine.length\n    await buffer.setCursorPosition(line, column + cursorOffset)\n\n    if (isSnippet) {\n        await snippetManager.insertSnippet(completion.insertText)\n    }\n}\n\nexport function getCompletionStart(\n    bufferLine: string,\n    cursorColumn: number,\n    completion: string,\n): number {\n    cursorColumn = Math.min(cursorColumn, bufferLine.length)\n\n    let x = cursorColumn\n    while (x >= 0) {\n        const subWord = bufferLine.substring(x, cursorColumn + 1)\n\n        if (completion.indexOf(subWord) === -1) {\n            break\n        }\n\n        x--\n    }\n\n    return x + 1\n}\n\nexport const getInsertText = (completionItem: types.CompletionItem): string => {\n    return completionItem.insertText || completionItem.label\n}\n\nexport function replacePrefixWithCompletion(\n    bufferLine: string,\n    basePosition: number,\n    cursorColumn: number,\n    completion: string,\n): string {\n    const startPosition = basePosition\n\n    const before = bufferLine.substring(0, startPosition)\n    const after = bufferLine.substring(cursorColumn, bufferLine.length)\n\n    return before + completion + after\n}\n\nexport interface CompletionMeetResult {\n    // Position - where the meet starts\n    position: number\n\n    // PositionToQuery - where the query request should start\n    positionToQuery: number\n\n    // Base - the currentg prefix of the completion\n    base: string\n\n    // Whether or not completiosn should be expanded / queriried\n    shouldExpandCompletions: boolean\n}\n\nexport const doesCharacterMatchTriggerCharacters = (\n    character: string,\n    triggerCharacters: string[],\n): boolean => {\n    return triggerCharacters.indexOf(character) >= 0\n}\n\n/**\n * Returns the start of the 'completion meet' along with the current base for completion\n */\nexport function getCompletionMeet(\n    line: string,\n    cursorColumn: number,\n    characterMatchRegex: RegExp,\n    completionTriggerCharacters: string[],\n): CompletionMeetResult {\n    // Clamp column to within string bounds\n    let col = Math.max(cursorColumn - 1, 0)\n    col = Math.min(col, line.length - 1)\n\n    let currentPrefix = \"\"\n\n    while (col >= 0 && col < line.length) {\n        const currentCharacter = line[col]\n\n        if (\n            !currentCharacter.match(characterMatchRegex) ||\n            doesCharacterMatchTriggerCharacters(currentCharacter, completionTriggerCharacters)\n        ) {\n            break\n        }\n\n        currentPrefix = currentCharacter + currentPrefix\n        col--\n    }\n\n    const basePos = col + 1\n\n    const isFromTriggerCharacter = doesCharacterMatchTriggerCharacters(\n        line[basePos - 1],\n        completionTriggerCharacters,\n    )\n\n    const isCharacterAfterCursor =\n        cursorColumn < line.length && line[cursorColumn].match(characterMatchRegex)\n\n    const shouldExpandCompletions =\n        (currentPrefix.length > 0 || isFromTriggerCharacter) && !isCharacterAfterCursor\n\n    const positionToQuery = isFromTriggerCharacter ? basePos : basePos + 1\n\n    return {\n        position: basePos,\n        positionToQuery,\n        base: currentPrefix,\n        shouldExpandCompletions,\n    }\n}\n\nexport const convertKindToIconName = (completionKind: types.CompletionItemKind) => {\n    switch (completionKind) {\n        case types.CompletionItemKind.Class:\n            return \"cube\"\n        case types.CompletionItemKind.Color:\n            return \"paint-brush\"\n        case types.CompletionItemKind.Constructor:\n            return \"building\"\n        case types.CompletionItemKind.Enum:\n            return \"sitemap\"\n        case types.CompletionItemKind.Field:\n            return \"var\"\n        case types.CompletionItemKind.File:\n            return \"file\"\n        case types.CompletionItemKind.Function:\n            return \"cog\"\n        case types.CompletionItemKind.Interface:\n            return \"plug\"\n        case types.CompletionItemKind.Keyword:\n            return \"key\"\n        case types.CompletionItemKind.Method:\n            return \"flash\"\n        case types.CompletionItemKind.Module:\n            return \"cubes\"\n        case types.CompletionItemKind.Property:\n            return \"wrench\"\n        case types.CompletionItemKind.Reference:\n            return \"chain\"\n        case types.CompletionItemKind.Snippet:\n            return \"align-justify\"\n        case types.CompletionItemKind.Text:\n            return \"align-justify\"\n        case types.CompletionItemKind.Unit:\n            return \"tag\"\n        case types.CompletionItemKind.Value:\n            return \"lock\"\n        case types.CompletionItemKind.Variable:\n            return \"code\"\n        default:\n            return \"question\"\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/CompletionsRequestor.ts",
    "content": "/**\n * CompletionsRequestor.ts\n *\n * Abstraction over the action of requesting completions\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Log from \"oni-core-logging\"\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { LanguageManager } from \"./../Language\"\nimport { IServerCapabilities } from \"./../Language/ServerCapabilities\"\n\nexport interface CompletionsRequestContext {\n    language: string\n    filePath: string\n    line: number\n    column: number\n    meetCharacter: string\n    textMateScopes: string[]\n}\n\nexport interface ICompletionsRequestor {\n    getCompletions(completionContext: CompletionsRequestContext): Promise<types.CompletionItem[]>\n    getCompletionDetails(\n        fileLanguage: string,\n        filePath: string,\n        completionItem: types.CompletionItem,\n    ): Promise<types.CompletionItem>\n}\n\nexport class LanguageServiceCompletionsRequestor implements ICompletionsRequestor {\n    constructor(private _languageManager: LanguageManager) {}\n\n    public async getCompletions(\n        context: CompletionsRequestContext,\n    ): Promise<types.CompletionItem[]> {\n        if (Log.isDebugLoggingEnabled()) {\n            Log.debug(\n                `[COMPLETION] Requesting completions at line ${context.line} and character ${\n                    context.column\n                }`,\n            )\n        }\n\n        const args = {\n            textDocument: {\n                uri: Helpers.wrapPathInFileUri(context.filePath),\n            },\n            position: {\n                line: context.line,\n                character: context.column,\n            },\n        }\n        let result = null\n        try {\n            result = await this._languageManager.sendLanguageServerRequest(\n                context.language,\n                context.filePath,\n                \"textDocument/completion\",\n                args,\n            )\n        } catch (ex) {\n            Log.verbose(ex)\n        }\n\n        if (!result) {\n            return null\n        }\n\n        const items = getCompletionItems(result)\n\n        if (!items) {\n            return null\n        }\n\n        if (Log.isDebugLoggingEnabled()) {\n            Log.debug(`[COMPLETION] Got completions: ${items.length}`)\n        }\n\n        return items\n    }\n\n    public async getCompletionDetails(\n        language: string,\n        filePath: string,\n        completionItem: types.CompletionItem,\n    ): Promise<types.CompletionItem> {\n        const caps: IServerCapabilities = await this._languageManager.getCapabilitiesForLanguage(\n            language,\n        )\n        if (!caps.completionProvider.resolveProvider) {\n            return completionItem\n        }\n        let result\n        try {\n            result = await this._languageManager.sendLanguageServerRequest(\n                language,\n                filePath,\n                \"completionItem/resolve\",\n                completionItem,\n            )\n        } catch (ex) {\n            Log.verbose(ex)\n        }\n\n        if (!result) {\n            return null\n        }\n\n        return result\n    }\n}\n\nconst getCompletionItems = (\n    items: types.CompletionItem[] | types.CompletionList,\n): types.CompletionItem[] => {\n    if (!items) {\n        return []\n    }\n\n    if (Array.isArray(items)) {\n        return items\n    } else {\n        return items.items || []\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Completion/index.ts",
    "content": "export * from \"./Completion\"\nexport * from \"./CompletionProviders\"\nexport * from \"./CompletionsRequestor\"\nexport * from \"./CompletionUtility\"\n"
  },
  {
    "path": "browser/src/Services/Configuration/Configuration.ts",
    "content": "/**\n * Configuration.ts\n */\n\nimport { merge } from \"lodash\"\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IDisposable, IEvent } from \"oni-types\"\nimport { applyDefaultKeyBindings } from \"./../../Input/KeyBindings\"\nimport * as Performance from \"./../../Performance\"\nimport { diff } from \"./../../Utility\"\n\nimport { IConfigurationEditor, JavaScriptConfigurationEditor } from \"./ConfigurationEditor\"\nimport { DefaultConfiguration } from \"./DefaultConfiguration\"\nimport { checkDeprecatedSettings } from \"./DeprecatedConfigurationValues\"\nimport { FileConfigurationProvider } from \"./FileConfigurationProvider\"\nimport { IConfigurationValues } from \"./IConfigurationValues\"\nimport { PersistedConfiguration } from \"./PersistentSettings\"\nimport * as UserConfiguration from \"./UserConfiguration\"\n\nexport interface IConfigurationProvider {\n    onConfigurationChanged: IEvent<void>\n    onConfigurationError: IEvent<Error>\n\n    getValues(): GenericConfigurationValues\n    getLastError(): Error | null\n\n    activate(api: Oni.Plugin.Api): void\n    deactivate(): void\n}\n\nexport interface GenericConfigurationValues {\n    [configKey: string]: any\n}\n\ninterface ConfigurationProviderInfo {\n    disposables: IDisposable[]\n}\n\nexport interface IConfigurationSettingValueChangedEvent<T> {\n    newValue: T\n    oldValue?: T\n}\n\nexport interface IConfigurationSetting<T> extends IDisposable {\n    onValueChanged: IEvent<IConfigurationSettingValueChangedEvent<T>>\n    getValue(): T\n}\n\nexport type ConfigurationSettingMergeStrategy<T> = (\n    higherPrecedenceValue: T,\n    lowerPrecedenceValue: T,\n) => T\n\nexport interface IConfigurationSettingMetadata<T> {\n    defaultValue?: T\n\n    // Comment that will be shown in the generated configuration\n    // metadata section\n    description?: string\n\n    // Whether or not the configuration value requires reloading\n    // the editor to be picked up. If the value can be incrementally\n    // applied, set this to true so we don't prompt the user to\n    // reload the editor.\n    requiresReload?: boolean\n\n    // TODO: Implement a merge strategy\n    // Specifies the merge strategy for a configuration setting\n    // By default, the higher precedence setting will be returned,\n    // but for things like arrays or objects, there may be a more\n    // involved merge strategy.\n    // mergeStrategy?: ConfigurationSettingMergeStrategy<T>\n}\n\nconst DefaultConfigurationSettings: IConfigurationSettingMetadata<any> = {\n    defaultValue: null,\n    description: null,\n    requiresReload: true,\n    // mergeStrategy: (higher: any, lower: any): any => higher,\n}\n\n/**\n * Interface describing persistence layer for configuration\n */\nexport interface IPersistedConfiguration {\n    getPersistedValues(): GenericConfigurationValues\n    setPersistedValues(configurationValues: GenericConfigurationValues): void\n}\n\nexport interface IConfigurationUpdateEvent {\n    requiresReload: boolean\n}\n\nexport class Configuration implements Oni.Configuration {\n    private _configurationProviders: IConfigurationProvider[] = []\n    private _onConfigurationChangedEvent: Event<Partial<IConfigurationValues>> = new Event<\n        Partial<IConfigurationValues>\n    >()\n    private _onConfigurationErrorEvent: Event<Error> = new Event<Error>()\n\n    private _onConfigurationUpdatedEvent = new Event<IConfigurationUpdateEvent>()\n\n    private _oniApi: Oni.Plugin.Api = null\n    private _config: GenericConfigurationValues = {}\n\n    private _setValues: { [configValue: string]: any } = {}\n    private _fileToProvider: { [key: string]: IConfigurationProvider } = {}\n    private _configProviderInfo = new Map<IConfigurationProvider, ConfigurationProviderInfo>()\n    private _configurationEditors: { [key: string]: IConfigurationEditor } = {}\n\n    private _settingMetadata: { [settingName: string]: IConfigurationSettingMetadata<any> } = {}\n    private _subscriptions: {\n        [settingName: string]: Array<Event<IConfigurationSettingValueChangedEvent<any>>>\n    } = {}\n\n    public get editor(): IConfigurationEditor {\n        const val = this.getValue(\"configuration.editor\")\n        return this._configurationEditors[val] || new JavaScriptConfigurationEditor()\n    }\n\n    public get onConfigurationError(): IEvent<Error> {\n        return this._onConfigurationErrorEvent\n    }\n\n    public get onConfigurationChanged(): IEvent<Partial<IConfigurationValues>> {\n        return this._onConfigurationChangedEvent\n    }\n\n    public get onConfigurationUpdated(): IEvent<IConfigurationUpdateEvent> {\n        return this._onConfigurationUpdatedEvent\n    }\n\n    constructor(\n        private _defaultConfiguration: GenericConfigurationValues = DefaultConfiguration,\n        private _persistedConfiguration: IPersistedConfiguration = new PersistedConfiguration(),\n    ) {\n        this._updateConfig()\n    }\n\n    public start(): void {\n        Performance.mark(\"Config.load.start\")\n\n        this.addConfigurationFile(UserConfiguration.getUserConfigFilePath())\n\n        Performance.mark(\"Config.load.end\")\n    }\n\n    public registerSetting<T>(\n        name: string,\n        options: IConfigurationSettingMetadata<T> = DefaultConfigurationSettings,\n    ): IConfigurationSetting<T> {\n        this._settingMetadata[name] = options\n\n        const currentValue = this.getValue(name, null)\n\n        if (options.defaultValue && currentValue === null) {\n            this.setValue(name, options.defaultValue)\n        }\n\n        const newEvent = new Event<IConfigurationSettingValueChangedEvent<any>>()\n        const subs: Array<Event<IConfigurationSettingValueChangedEvent<any>>> =\n            this._subscriptions[name] || []\n        this._subscriptions[name] = [...subs, newEvent]\n\n        const dispose = () => {\n            this._subscriptions[name] = this._subscriptions[name].filter(e => e !== newEvent)\n        }\n\n        const getValue = () => {\n            return this.getValue(name)\n        }\n\n        return {\n            onValueChanged: newEvent,\n            dispose,\n            getValue,\n        }\n    }\n\n    public registerEditor(id: string, editor: IConfigurationEditor): void {\n        this._configurationEditors[id] = editor\n    }\n\n    public addConfigurationFile(filePath: string): void {\n        Log.info(\"[Configuration] Adding file: \" + filePath)\n        const fp = new FileConfigurationProvider(filePath)\n        this.addConfigurationProvider(fp)\n        this._fileToProvider[filePath] = fp\n    }\n\n    public removeConfigurationFile(filePath: string): void {\n        Log.info(\"[Configuration] Removing file: \" + filePath)\n        const configProvider = this._fileToProvider[filePath]\n\n        if (configProvider) {\n            this.removeConfigurationProvider(configProvider)\n            this._fileToProvider[filePath] = null\n        }\n    }\n\n    public getErrors(): Error[] {\n        return this._configurationProviders.map(cfp => cfp.getLastError())\n    }\n\n    public addConfigurationProvider(configurationProvider: IConfigurationProvider): void {\n        this._configurationProviders.push(configurationProvider)\n\n        const d1 = configurationProvider.onConfigurationChanged.subscribe(() => {\n            Log.info(\"[Configuration] Got update.\")\n            this._updateConfig()\n        })\n\n        const d2 = configurationProvider.onConfigurationError.subscribe(error => {\n            this._onConfigurationErrorEvent.dispatch(error)\n        })\n\n        this._configProviderInfo.set(configurationProvider, {\n            disposables: [d1, d2],\n        })\n\n        this._updateConfig()\n    }\n\n    public removeConfigurationProvider(configurationProvider: IConfigurationProvider): void {\n        this._configurationProviders = this._configurationProviders.filter(\n            prov => prov !== configurationProvider,\n        )\n\n        const configurationInfo = this._configProviderInfo.get(configurationProvider)\n        configurationInfo.disposables.forEach(dispose => dispose.dispose())\n\n        this._configProviderInfo.delete(configurationProvider)\n\n        this._updateConfig()\n    }\n\n    public hasValue(configValue: keyof IConfigurationValues): boolean {\n        return !!this.getValue(configValue)\n    }\n\n    public setValue(valueName: string, value: any, persist: boolean = false): void {\n        return this.setValues({ [valueName]: value }, persist)\n    }\n\n    public setValues(configValues: { [configValue: string]: any }, persist: boolean = false): void {\n        this._setValues = configValues\n\n        const oldValues = {\n            ...this._config,\n        }\n\n        this._config = {\n            ...this._config,\n            ...configValues,\n        }\n\n        if (persist) {\n            this._persistedConfiguration.setPersistedValues(configValues)\n        }\n\n        this._onConfigurationChangedEvent.dispatch(configValues)\n\n        this._notifySubscribers(oldValues, this._config, Object.keys(configValues))\n    }\n\n    public getValue<K extends keyof IConfigurationValues>(configValue: K, defaultValue?: any) {\n        const v = this._config[configValue]\n        const valueExists = v !== undefined\n        return valueExists ? v : defaultValue\n    }\n\n    public getValues(): GenericConfigurationValues {\n        return { ...this._config }\n    }\n\n    public activate(oni: Oni.Plugin.Api): void {\n        this._oniApi = oni\n\n        this._activateIfOniObjectIsAvailable()\n    }\n\n    public getMetadata<T>(settingName: string): IConfigurationSettingMetadata<T> {\n        return this._settingMetadata[settingName] || null\n    }\n\n    private _updateConfig(): void {\n        const previousConfig = this._config\n        // Need a deep merge here to recursively update the config\n        let currentConfig = merge(\n            this._defaultConfiguration,\n            this._persistedConfiguration.getPersistedValues(),\n            this._setValues,\n        )\n\n        this._configurationProviders.forEach(configProvider => {\n            const configurationValues = configProvider.getValues()\n            currentConfig = { ...currentConfig, ...configurationValues }\n        })\n\n        this._config = currentConfig\n\n        checkDeprecatedSettings(this._config)\n\n        this._deactivate()\n        this._activateIfOniObjectIsAvailable()\n\n        this._notifyListeners(previousConfig)\n    }\n\n    private _activateIfOniObjectIsAvailable(): void {\n        if (this._oniApi) {\n            applyDefaultKeyBindings(this._oniApi, this)\n            this._configurationProviders.forEach(configurationProvider =>\n                configurationProvider.activate(this._oniApi),\n            )\n        }\n    }\n\n    private _deactivate(): void {\n        this._configurationProviders.forEach(configurationProvider =>\n            configurationProvider.deactivate(),\n        )\n        if (this._config && this._config.deactivate) {\n            this._config.deactivate()\n        }\n    }\n\n    private _notifyListeners(previousConfig?: Partial<IConfigurationValues>): void {\n        previousConfig = previousConfig || {}\n\n        const changedValues = diff(this._config, previousConfig)\n\n        const diffObject = changedValues.reduce(\n            (previous: Partial<IConfigurationValues>, current: string) => {\n                const currentValue = this._config[current]\n\n                // Skip functions, because those will always be different\n                if (currentValue && typeof currentValue === \"function\") {\n                    return previous\n                }\n\n                return {\n                    ...previous,\n                    [current]: this._config[current],\n                }\n            },\n            {},\n        )\n\n        this._onConfigurationChangedEvent.dispatch(diffObject)\n\n        this._notifySubscribers(previousConfig, this._config, Object.keys(diffObject))\n    }\n\n    private _notifySubscribers(oldValues: any, newValues: any, changedKeys: string[]): void {\n        let requiresReload = false\n        changedKeys.forEach(name => {\n            const settings = this._subscriptions[name]\n\n            const metadata = this.getMetadata(name)\n\n            requiresReload = requiresReload || !metadata || metadata.requiresReload\n\n            if (!settings) {\n                return\n            }\n\n            const args = {\n                oldValue: oldValues[name],\n                newValue: newValues[name],\n            }\n\n            settings.forEach(evt => evt.dispatch(args))\n        })\n\n        this._onConfigurationUpdatedEvent.dispatch({ requiresReload: true })\n    }\n}\n\nexport const configuration = new Configuration()\n"
  },
  {
    "path": "browser/src/Services/Configuration/ConfigurationCommands.ts",
    "content": "/**\n * ConfigurationCommands\n */\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { EditorManager } from \"./../EditorManager\"\n\nimport { Configuration } from \"./Configuration\"\nimport { ConfigurationEditManager } from \"./ConfigurationEditor\"\n\nimport { getUserConfigFilePath } from \"./index\"\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n) => {\n    const configurationEditManager = new ConfigurationEditManager(configuration, editorManager)\n\n    commandManager.registerCommand({\n        command: \"oni.config.openUserConfig\",\n        name: \"Configuration: Edit User Config\",\n        detail: \"Edit user configuration file for Oni\",\n        execute: () => configurationEditManager.editConfiguration(getUserConfigFilePath()),\n    })\n\n    commandManager.registerCommand({\n        command: \"oni.config.openConfigJs\",\n        name: null,\n        detail: null,\n        execute: () => configurationEditManager.editConfiguration(getUserConfigFilePath()),\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/ConfigurationEditor.ts",
    "content": "/**\n * ConfigurationEditor.ts\n */\n\nimport * as fs from \"fs\"\nimport * as Oni from \"oni-api\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { EditorManager } from \"./../EditorManager\"\n\nimport { Configuration } from \"./Configuration\"\nimport { DefaultConfiguration } from \"./DefaultConfiguration\"\n\n// For configuring Oni, JavaScript is the de-facto language, and the configuration\n// today will _always_ happen through `config.js`\n//\n// However, we want to support configuring in dialects of JS, like:\n// - TypeScript\n// - Reason\n// - ClojureScript\n// - CoffeeScript\n// - Script# (C#)\n// etc...\n//\n// Or even wasm languages!\n//\n// `IConfigurationEditor` provides an interface for this functionality.\n//\n// The expectation is that implementors of this will specify a separate file,\n// and implement functionality for compilng to JavaScript.\nexport interface IConfigurationEditor {\n    // For configuration editors that use a different language\n    // (TypeScript, Reason, etc), this specifies the file\n    // that should be opened for editing.\n    editConfiguration(configurationFilePath: string): Promise<string>\n\n    // When the edit file is saved, this is responsible for transpiling the contents\n    // to javascript.\n    transpileConfigurationToJavaScript(contents: string): Promise<string>\n}\n\nexport class JavaScriptConfigurationEditor {\n    public async editConfiguration(configurationFilePath: string): Promise<string> {\n        // Create default file, if it doesn't already exist\n        if (!fs.existsSync(configurationFilePath)) {\n            const defaultConfigJsPath = path.join(__dirname, \"configuration\", \"config.default.js\")\n            const defaultConfigLines = fs.readFileSync(defaultConfigJsPath, \"utf8\")\n\n            mkdirp.sync(path.dirname(configurationFilePath))\n            fs.writeFileSync(configurationFilePath, defaultConfigLines)\n        }\n\n        return configurationFilePath\n    }\n\n    public async transpileConfigurationToJavaScript(contents: string): Promise<string> {\n        return contents\n    }\n}\n\nexport interface IConfigurationEditInfo {\n    editor: IConfigurationEditor\n    destinationConfigFilePath: string\n}\n\nexport class ConfigurationEditManager {\n    private _fileToEditor: { [filePath: string]: IConfigurationEditInfo } = {}\n\n    constructor(private _configuration: Configuration, private _editorManager: EditorManager) {\n        this._editorManager.anyEditor.onBufferSaved.subscribe(evt => {\n            const activeEditingSession = this._fileToEditor[evt.filePath]\n\n            if (activeEditingSession) {\n                const currentBuffer = this._editorManager.activeEditor.activeBuffer\n                if (currentBuffer.filePath === evt.filePath) {\n                    this._transpileConfiguration(\n                        currentBuffer,\n                        activeEditingSession.editor,\n                        activeEditingSession.destinationConfigFilePath,\n                    )\n                }\n            }\n        })\n    }\n\n    public async editConfiguration(configFile: string): Promise<void> {\n        Log.info(\"[ConfigurationEditManager::editConfiguration]: \" + configFile)\n        const editor = this._configuration.editor\n        const editFile = await editor.editConfiguration(configFile)\n\n        const normalizedEditFile = !!editFile ? editFile : configFile\n\n        if (editFile) {\n            this._fileToEditor[editFile] = {\n                editor,\n                destinationConfigFilePath: configFile,\n            }\n        } else {\n            this._fileToEditor[configFile] = {\n                editor: new JavaScriptConfigurationEditor(),\n                destinationConfigFilePath: configFile,\n            }\n        }\n\n        const showReferenceBuffer = this._configuration.getValue(\n            \"configuration.showReferenceBuffer\",\n        )\n\n        if (showReferenceBuffer) {\n            // Create the buffer with the list of all the available options\n            await this._createReadonlyReferenceBuffer()\n\n            // Open the actual configuration file\n            await this._editorManager.activeEditor.openFile(normalizedEditFile, {\n                openMode: Oni.FileOpenMode.VerticalSplit,\n            })\n        } else {\n            await this._editorManager.activeEditor.openFile(normalizedEditFile, {\n                openMode: Oni.FileOpenMode.Edit,\n            })\n        }\n    }\n\n    private async _createReadonlyReferenceBuffer() {\n        const referenceBuffer = await this._editorManager.activeEditor.openFile(\"reference\", {\n            openMode: Oni.FileOpenMode.NewTab,\n        })\n\n        // Format the default configuration values as a pretty JSON object, then\n        // set it as the reference buffer content\n        const referenceContent = JSON.stringify(DefaultConfiguration, null, \"  \")\n        await Promise.all([\n            referenceBuffer.setLines(0, 1, referenceContent.split(\"\\n\")),\n            // FIXME: needs to be added to the Oni.Buffers API\n            (referenceBuffer as any).setLanguage(\"json\"),\n            (referenceBuffer as any).setScratchBuffer(),\n        ])\n    }\n\n    private async _transpileConfiguration(\n        buffer: Oni.Buffer,\n        editor: IConfigurationEditor,\n        destinationConfigFilePath: string,\n    ): Promise<void> {\n        Log.info(\n            `[ConfigurationEditManager::_transpileConfiguration] Transpiling ${\n                buffer.filePath\n            } to ${destinationConfigFilePath}`,\n        )\n\n        const contents = await buffer.getLines()\n        const joinedContents = contents.join(os.EOL)\n        const transpiledContents = await editor.transpileConfigurationToJavaScript(joinedContents)\n\n        if (\n            buffer.filePath === destinationConfigFilePath &&\n            joinedContents === transpiledContents\n        ) {\n            Log.info(\n                `[ConfigurationEditManager::_transpileConfiguration] Aborting transpile since destination file / source file + contents are the same (expected for JavaScript strategy).`,\n            )\n            return\n        }\n\n        fs.writeFileSync(destinationConfigFilePath, transpiledContents)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/DefaultConfiguration.ts",
    "content": "/**\n * DefaultConfiguration.ts\n *\n * Specifies Oni default settings\n */\n\nimport * as os from \"os\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as path from \"path\"\n\nimport * as Platform from \"./../../Platform\"\n\nimport { IConfigurationValues } from \"./IConfigurationValues\"\nimport { ocamlAndReasonConfiguration, ocamlLanguageServerPath } from \"./ReasonConfiguration\"\n\nconst noop = () => {} // tslint:disable-line no-empty\n\nconst cssLanguageServerPath = path.join(\n    __dirname,\n    \"node_modules\",\n    \"vscode-css-languageserver-bin\",\n    \"cssServerMain.js\",\n)\nconst htmlLanguageServerPath = path.join(\n    __dirname,\n    \"node_modules\",\n    \"vscode-html-languageserver-bin\",\n    \"htmlServerMain.js\",\n)\n\nconst BaseConfiguration: IConfigurationValues = {\n    activate: noop,\n    deactivate: noop,\n\n    \"autoUpdate.enabled\": false,\n\n    \"browser.defaultUrl\": \"https://duckduckgo.com\",\n    \"configuration.editor\": \"typescript\",\n    \"configuration.showReferenceBuffer\": true,\n\n    \"debug.fixedSize\": null,\n    \"debug.neovimPath\": null,\n    \"debug.persistOnNeovimExit\": false,\n    \"debug.detailedSessionLogging\": false,\n    \"debug.showTypingPrediction\": false,\n    \"debug.showNotificationOnError\": process.env.NODE_ENV !== \"production\",\n\n    \"debug.fakeLag.languageServer\": null,\n    \"debug.fakeLag.neovimInput\": null,\n\n    \"wildmenu.mode\": true,\n    \"commandline.mode\": true,\n    \"commandline.icons\": true,\n    \"experimental.preview.enabled\": false,\n    \"experimental.welcome.enabled\": false,\n    \"experimental.particles.enabled\": false,\n    \"experimental.sessions.enabled\": false,\n    \"experimental.sessions.directory\": null,\n    \"experimental.vcs.sidebar\": false,\n    \"experimental.vcs.blame.enabled\": false,\n    \"experimental.vcs.blame.mode\": \"auto\",\n    \"experimental.vcs.blame.timeout\": 800,\n\n    \"experimental.colorHighlight.enabled\": false,\n    \"experimental.colorHighlight.filetypes\": [\n        \".css\",\n        \".js\",\n        \".jsx\",\n        \".tsx\",\n        \".ts\",\n        \".re\",\n        \".sass\",\n        \".scss\",\n        \".less\",\n        \".pcss\",\n        \".sss\",\n        \".stylus\",\n        \".xml\",\n        \".svg\",\n    ],\n    \"experimental.indentLines.enabled\": false,\n    \"experimental.indentLines.color\": null,\n    \"experimental.indentLines.skipFirst\": false,\n    \"experimental.indentLines.bannedFiletypes\": [],\n    \"experimental.markdownPreview.enabled\": false,\n    \"experimental.markdownPreview.autoScroll\": true,\n    \"experimental.markdownPreview.syntaxHighlights\": true,\n    \"experimental.markdownPreview.syntaxTheme\": \"atom-one-dark\",\n\n    \"experimental.neovim.transport\": \"stdio\",\n    // TODO: Enable pipe transport for Windows\n    // \"experimental.neovim.transport\": Platform.isWindows() ? \"pipe\" : \"stdio\",\n\n    \"editor.maxLinesForLanguageServices\": 2500,\n    \"editor.textMateHighlighting.enabled\": true,\n\n    \"autoClosingPairs.enabled\": true,\n    \"autoClosingPairs.default\": [\n        { open: \"{\", close: \"}\" },\n        { open: \"[\", close: \"]\" },\n        { open: \"(\", close: \")\" },\n    ],\n\n    \"oni.audio.bellUrl\": null,\n\n    \"oni.useDefaultConfig\": true,\n\n    \"oni.enhancedSyntaxHighlighting\": true,\n\n    \"oni.userShell\": undefined,\n\n    \"oni.loadInitVim\": false,\n\n    \"oni.hideMenu\": false,\n\n    \"oni.exclude\": [\"node_modules\", \".git\"],\n    \"oni.bookmarks\": [],\n\n    \"editor.renderer\": \"canvas\",\n\n    \"editor.backgroundOpacity\": 1.0,\n    \"editor.backgroundImageUrl\": null,\n    \"editor.backgroundImageSize\": \"cover\",\n\n    \"editor.clipboard.enabled\": true,\n    \"editor.clipboard.synchronizeYank\": true,\n    \"editor.clipboard.synchronizeDelete\": false,\n\n    \"editor.definition.enabled\": true,\n    \"editor.quickInfo.enabled\": true,\n    \"editor.quickInfo.delay\": 500,\n\n    \"editor.completions.mode\": \"oni\",\n    \"editor.errors.slideOnFocus\": true,\n    \"editor.formatting.formatOnSwitchToNormalMode\": false,\n\n    \"editor.fontLigatures\": true,\n    \"editor.fontSize\": \"12px\",\n    \"editor.fontWeight\": \"normal\",\n    \"editor.fontFamily\": \"\",\n\n    \"editor.linePadding\": 2,\n\n    \"editor.quickOpen.execCommand\": undefined,\n    \"editor.quickOpen.filterStrategy\": \"vscode\",\n    \"editor.quickOpen.defaultOpenMode\": Oni.FileOpenMode.Edit,\n    \"editor.quickOpen.alternativeOpenMode\": Oni.FileOpenMode.ExistingTab,\n    \"editor.quickOpen.showHidden\": true,\n\n    \"quickOpen.defaultOpenMode\": Oni.FileOpenMode.Edit,\n\n    \"editor.split.mode\": \"native\",\n\n    \"editor.typingPrediction\": true,\n\n    \"editor.scrollBar.visible\": true,\n\n    \"editor.scrollBar.cursorTick.visible\": true,\n\n    \"editor.fullScreenOnStart\": false,\n    \"editor.maximizeScreenOnStart\": false,\n\n    \"editor.cursorLine\": true,\n    \"editor.cursorLineOpacity\": 0.1,\n\n    \"editor.cursorColumn\": false,\n    \"editor.cursorColumnOpacity\": 0.1,\n\n    \"editor.tokenColors\": [],\n\n    \"editor.imageLayerExtensions\": [\".gif\", \".jpg\", \".jpeg\", \".bmp\", \".png\"],\n\n    \"explorer.persistDeletedFiles\": true,\n    \"explorer.maxUndoFileSizeInBytes\": 500_000,\n\n    \"environment.additionalPaths\": [],\n    \"environment.additionalVariables\": {},\n\n    \"keyDisplayer.showInInsertMode\": false,\n\n    \"language.html.languageServer.command\": htmlLanguageServerPath,\n    \"language.html.languageServer.arguments\": [\"--stdio\"],\n\n    \"language.go.languageServer.command\": \"go-langserver\",\n    \"language.go.textMateGrammar\": path.join(__dirname, \"extensions\", \"go\", \"syntaxes\", \"go.json\"),\n\n    \"language.vue.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"vue\",\n        \"syntaxes\",\n        \"vue.json\",\n    ),\n\n    \"language.python.languageServer.command\": \"pyls\",\n    \"language.cpp.languageServer.command\": \"clangd\",\n    \"language.c.languageServer.command\": \"clangd\",\n\n    \"language.css.languageServer.command\": cssLanguageServerPath,\n    \"language.css.languageServer.arguments\": [\"--stdio\"],\n    \"language.css.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"css\",\n        \"syntaxes\",\n        \"css.tmLanguage.json\",\n    ),\n    \"language.css.tokenRegex\": \"[$_a-zA-Z0-9-]\",\n\n    \"language.elixir.textMateGrammar\": {\n        \".ex\": path.join(__dirname, \"extensions\", \"elixir\", \"syntaxes\", \"elixir.tmLanguage.json\"),\n        \".exs\": path.join(__dirname, \"extensions\", \"elixir\", \"syntaxes\", \"elixir.tmLanguage.json\"),\n        \".eex\": path.join(__dirname, \"extensions\", \"elixir\", \"syntaxes\", \"eex.tmLanguage.json\"),\n        \".html.eex\": path.join(\n            __dirname,\n            \"extensions\",\n            \"elixir\",\n            \"syntaxes\",\n            \"html(eex).tmLanguage.json\",\n        ),\n    },\n\n    \"language.less.languageServer.command\": cssLanguageServerPath,\n    \"language.less.languageServer.arguments\": [\"--stdio\"],\n    \"language.less.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"less\",\n        \"syntaxes\",\n        \"less.tmLanguage.json\",\n    ),\n    \"language.less.tokenRegex\": \"[$_a-zA-Z0-9-]\",\n\n    \"language.scss.languageServer.command\": cssLanguageServerPath,\n    \"language.scss.languageServer.arguments\": [\"--stdio\"],\n    \"language.scss.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"scss\",\n        \"syntaxes\",\n        \"scss.json\",\n    ),\n    \"language.scss.tokenRegex\": \"[$_a-zA-Z0-9-]\",\n\n    \"language.reason.languageServer.command\": ocamlLanguageServerPath,\n    \"language.reason.languageServer.arguments\": [\"--stdio\"],\n    \"language.reason.languageServer.rootFiles\": [\".merlin\", \"bsconfig.json\"],\n    \"language.reason.languageServer.configuration\": ocamlAndReasonConfiguration,\n    \"language.reason.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"reason\",\n        \"syntaxes\",\n        \"reason.json\",\n    ),\n\n    \"language.ocaml.languageServer.command\": ocamlLanguageServerPath,\n    \"language.ocaml.languageServer.arguments\": [\"--stdio\"],\n    \"language.ocaml.languageServer.configuration\": ocamlAndReasonConfiguration,\n\n    \"language.haskell.languageServer.command\": \"stack\",\n    \"language.haskell.languageServer.arguments\": [\"exec\", \"--\", \"hie\", \"--lsp\"],\n    \"language.haskell.languageServer.rootFiles\": [\".git\"],\n    \"language.haskell.languageServer.configuration\": {},\n\n    \"language.typescript.completionTriggerCharacters\": [\".\", \"/\", \"\\\\\"],\n    \"language.typescript.textMateGrammar\": {\n        \".ts\": path.join(\n            __dirname,\n            \"extensions\",\n            \"typescript\",\n            \"syntaxes\",\n            \"TypeScript.tmLanguage.json\",\n        ),\n        \".tsx\": path.join(\n            __dirname,\n            \"extensions\",\n            \"typescript\",\n            \"syntaxes\",\n            \"TypeScriptReact.tmLanguage.json\",\n        ),\n    },\n    \"language.lua.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"lua\",\n        \"syntaxes\",\n        \"lua.tmLanguage.json\",\n    ),\n    \"language.clojure.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"clojure\",\n        \"syntaxes\",\n        \"clojure.tmLanguage.json\",\n    ),\n    \"language.ruby.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"ruby\",\n        \"syntaxes\",\n        \"ruby.tmLanguage.json\",\n    ),\n    \"language.swift.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"swift\",\n        \"syntaxes\",\n        \"swift.tmLanguage.json\",\n    ),\n    \"language.rust.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"rust\",\n        \"syntaxes\",\n        \"rust.tmLanguage.json\",\n    ),\n    \"language.php.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"php\",\n        \"syntaxes\",\n        \"php.tmLanguage.json\",\n    ),\n    \"language.objc.textMateGrammar\": {\n        \".m\": path.join(\n            __dirname,\n            \"extensions\",\n            \"objective-c\",\n            \"syntaxes\",\n            \"objective-c.tmLanguage.json\",\n        ),\n        \".h\": path.join(\n            __dirname,\n            \"extensions\",\n            \"objective-c\",\n            \"syntaxes\",\n            \"objective-c.tmLanguage.json\",\n        ),\n    },\n    \"language.objcpp.textMateGrammar\": {\n        \".mm\": path.join(\n            __dirname,\n            \"extensions\",\n            \"objective-c++\",\n            \"syntaxes\",\n            \"objective-c++.tmLanguage.json\",\n        ),\n    },\n    \"language.python.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"python\",\n        \"syntaxes\",\n        \"python.tmLanguage.json\",\n    ),\n    \"language.sh.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"shell\",\n        \"syntaxes\",\n        \"shell.tmLanguage.json\",\n    ),\n    \"language.zsh.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"shell\",\n        \"syntaxes\",\n        \"shell.tmLanguage.json\",\n    ),\n    \"language.markdown.textMateGrammar\": {\n        \".md\": path.join(\n            __dirname,\n            \"extensions\",\n            \"markdown\",\n            \"syntaxes\",\n            \"markdown.tmLanguage.json\",\n        ),\n        \".markdown\": path.join(\n            __dirname,\n            \"extensions\",\n            \"markdown\",\n            \"syntaxes\",\n            \"markdown.tmLanguage.json\",\n        ),\n        \".mkd\": path.join(\n            __dirname,\n            \"extensions\",\n            \"markdown\",\n            \"syntaxes\",\n            \"markdown.tmLanguage.json\",\n        ),\n        \".mdown\": path.join(\n            __dirname,\n            \"extensions\",\n            \"markdown\",\n            \"syntaxes\",\n            \"markdown.tmLanguage.json\",\n        ),\n    },\n    \"language.java.textMateGrammar\": {\n        \".java\": path.join(__dirname, \"extensions\", \"java\", \"syntaxes\", \"Java.tmLanguage.json\"),\n        \".jar\": path.join(__dirname, \"extensions\", \"java\", \"syntaxes\", \"Java.tmLanguage.json\"),\n    },\n    \"language.cs.textMateGrammar\": path.join(\n        __dirname,\n        \"extensions\",\n        \"csharp\",\n        \"syntaxes\",\n        \"csharp.tmLanguage.json\",\n    ),\n    \"language.javascript.completionTriggerCharacters\": [\".\", \"/\", \"\\\\\"],\n    \"language.javascript.textMateGrammar\": {\n        \".js\": path.join(\n            __dirname,\n            \"extensions\",\n            \"javascript\",\n            \"syntaxes\",\n            \"JavaScript.tmLanguage.json\",\n        ),\n        \".jsx\": path.join(\n            __dirname,\n            \"extensions\",\n            \"javascript\",\n            \"syntaxes\",\n            \"JavaScriptReact.tmLanguage.json\",\n        ),\n    },\n\n    \"learning.enabled\": true,\n    \"achievements.enabled\": true,\n\n    \"menu.caseSensitive\": \"smart\",\n    \"menu.rowHeight\": 40,\n    \"menu.maxItemsToShow\": 8,\n\n    \"notifications.enabled\": true,\n\n    \"recorder.copyScreenshotToClipboard\": false,\n    \"recorder.outputPath\": os.tmpdir(),\n\n    \"sidebar.enabled\": true,\n    \"sidebar.default.open\": true,\n    \"sidebar.width\": \"15em\",\n\n    \"sidebar.marks.enabled\": false,\n    \"sidebar.plugins.enabled\": false,\n\n    \"snippets.enabled\": true,\n    \"snippets.userSnippetFolder\": null,\n\n    \"statusbar.enabled\": true,\n    \"statusbar.fontSize\": \"0.9em\",\n    \"statusbar.priority\": {\n        \"oni.status.workingDirectory\": 0,\n        \"oni.status.linenumber\": 2,\n        \"oni.status.gitHubRepo\": 0,\n        \"oni.status.mode\": 1,\n        \"oni.status.filetype\": 1,\n        \"oni.status.git\": 3,\n    },\n\n    \"oni.plugins.prettier\": {\n        settings: {\n            semi: false,\n            tabWidth: 2,\n            useTabs: false,\n            singleQuote: false,\n            trailingComma: \"es5\",\n            bracketSpacing: true,\n            jsxBracketSameLine: false,\n            arrowParens: \"avoid\",\n            printWidth: 80,\n        },\n        formatOnSave: false,\n        enabled: false,\n    },\n\n    \"tabs.mode\": \"tabs\",\n    \"tabs.height\": \"2.5em\",\n    \"tabs.highlight\": true,\n    \"tabs.maxWidth\": \"30em\",\n    \"tabs.showFileIcon\": true,\n    \"tabs.showIndex\": false,\n    \"tabs.wrap\": false,\n    \"tabs.dirtyMarker.userColor\": \"\",\n\n    \"terminal.shellCommand\": null,\n\n    \"ui.animations.enabled\": true,\n    \"ui.colorscheme\": \"nord\",\n    \"ui.iconTheme\": \"theme-icons-seti\",\n    \"ui.fontFamily\":\n        \"BlinkMacSystemFont, 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif\",\n    \"ui.fontSize\": \"13px\",\n    \"ui.fontSmoothing\": \"auto\",\n\n    \"workspace.defaultWorkspace\": null,\n    \"workspace.autoDetectWorkspace\": \"noworkspace\",\n    \"workspace.autoDetectRootFiles\": [\n        \".git\",\n        \"node_modules\",\n        \".svn\",\n        \"package.json\",\n        \".hg\",\n        \".bzr\",\n        \"build.xml\",\n    ],\n}\n\nconst MacConfigOverrides: Partial<IConfigurationValues> = {\n    \"editor.fontFamily\": \"Menlo\",\n    \"environment.additionalPaths\": [\"/usr/bin\", \"/usr/local/bin\"],\n}\n\nconst WindowsConfigOverrides: Partial<IConfigurationValues> = {\n    \"editor.fontFamily\": \"Consolas\",\n}\n\nconst LinuxConfigOverrides: Partial<IConfigurationValues> = {\n    \"editor.fontFamily\": \"DejaVu Sans Mono\",\n    \"environment.additionalPaths\": [\"/usr/bin\", \"/usr/local/bin\"],\n}\n\nconst PlatformConfigOverride = Platform.isWindows()\n    ? WindowsConfigOverrides\n    : Platform.isLinux()\n        ? LinuxConfigOverrides\n        : MacConfigOverrides\n\nexport const DefaultConfiguration = {\n    ...BaseConfiguration,\n    ...PlatformConfigOverride,\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/DeprecatedConfigurationValues.ts",
    "content": "/**\n * DeprecatedConfigurationValues\n *\n * The purpose of this is to give users a heads up when we plan on deprecating a configuration,\n * by providing them with a notice. As we move towards v1, we'll want to have some sort of\n * deprecation policy in place - like we'll support deprecated configurations for x releases.\n */\n\nimport * as Log from \"oni-core-logging\"\n\nexport interface IDeprecatedConfigurationInfo {\n    replacementConfigurationName: string\n    documentationUrl: string\n}\n\nconst deprecatedSettings: {\n    [deprecatedConfigurationName: string]: IDeprecatedConfigurationInfo\n} = {\n    \"editor.completions.enabled\": {\n        replacementConfigurationName: \"editor.completions.mode\",\n        documentationUrl: \"https://github.com/onivim/oni/wiki/Configuration#editor\",\n    },\n}\n\nexport const checkDeprecatedSettings = (config: { [key: string]: any }): void => {\n    Object.keys(config).forEach(configurationName => {\n        if (deprecatedSettings[configurationName]) {\n            const deprecationInfo = deprecatedSettings[configurationName]\n            Log.warn(\n                `Configuration setting '${configurationName}' is deprecated and will be replaced with '${\n                    deprecationInfo.replacementConfigurationName\n                }'. See more info at: ${deprecationInfo.documentationUrl}`,\n            )\n        }\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/FileConfigurationProvider.ts",
    "content": "/**\n * FileConfigurationProvider\n *\n * Implementation of a configuration provider backed by a file\n */\n\nimport * as fs from \"fs\"\nimport * as isError from \"lodash/isError\"\nimport * as mkdirp from \"mkdirp\"\nimport * as path from \"path\"\nimport * as vm from \"vm\"\n\nimport \"rxjs/add/operator/debounceTime\"\nimport { Subject } from \"rxjs/Subject\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { IConfigurationProvider } from \"./Configuration\"\nimport { IConfigurationValues } from \"./IConfigurationValues\"\n// import * as Utility from \"./../../Utility\"\n\nconst CONFIG_UPDATE_DEBOUNCE_TIME = 100 /*ms */\n\nexport class FileConfigurationProvider implements IConfigurationProvider {\n    private _configurationFilePath: string\n    private _containingFolder: string\n    private _configurationChangedEvent = new Event<void>()\n    private _configurationErrorEvent = new Event<Error>()\n    private _latestConfiguration: Partial<IConfigurationValues> = null\n    private _lastError: Error | null = null\n    private _configEverHadValue: boolean = false\n\n    private _configChangedObservable: Subject<void>\n    private _configErrorObservable: Subject<Error>\n\n    public get onConfigurationChanged(): IEvent<void> {\n        return this._configurationChangedEvent\n    }\n\n    public get onConfigurationError(): IEvent<Error> {\n        return this._configurationErrorEvent\n    }\n\n    constructor(filePath: string) {\n        this._configChangedObservable = new Subject<void>()\n        this._configErrorObservable = new Subject<Error>()\n\n        this._configChangedObservable\n            .debounceTime(CONFIG_UPDATE_DEBOUNCE_TIME)\n            .subscribe(() => this._configurationChangedEvent.dispatch())\n\n        this._configErrorObservable\n            .debounceTime(CONFIG_UPDATE_DEBOUNCE_TIME)\n            .subscribe((err: Error) => this._configurationErrorEvent.dispatch(err))\n\n        this._configurationFilePath = filePath\n        this._containingFolder = path.dirname(filePath)\n\n        if (!fs.existsSync(this._containingFolder)) {\n            mkdirp.sync(this._containingFolder)\n        }\n\n        // use watch() on the directory rather than on config.js because it watches\n        // file references and changing a file in Vim typically saves a tmp file\n        // then moves it over to the original filename, causing watch() to lose its\n        // reference. Instead, watch() can watch the folder for the file changes\n        // and continue to fire when file references are swapped out.\n        // Unfortunately, this also means the 'change' event fires twice.\n        // I could use watchFile() but that polls every 5 seconds.  Not ideal.\n        fs.watch(this._containingFolder, (event, filename) => {\n            if (\n                (event === \"change\" && filename === \"config.js\") ||\n                (event === \"rename\" && filename === \"config.js\")\n            ) {\n                // invalidate the Config currently stored in cache\n                delete global[\"require\"].cache[global[\"require\"].resolve(filePath)] // tslint:disable-line no-string-literal\n                this._getLatestConfig()\n            }\n        })\n\n        this._getLatestConfig()\n    }\n\n    public getValues(): Partial<IConfigurationValues> {\n        return this._latestConfiguration\n    }\n\n    public getLastError(): Error | null {\n        return this._lastError\n    }\n\n    public activate(api: Oni.Plugin.Api): void {\n        if (this._latestConfiguration && this._latestConfiguration.activate) {\n            try {\n                this._latestConfiguration.activate(api)\n            } catch (e) {\n                alert(\n                    \"[Config Error] Failed to activate \" +\n                        this._configurationFilePath +\n                        \":\\n\" +\n                        (e as Error).message,\n                )\n            }\n        }\n    }\n\n    public deactivate(): void {\n        if (this._latestConfiguration && this._latestConfiguration.deactivate) {\n            this._latestConfiguration.deactivate()\n        }\n    }\n\n    private _notifyConfigurationChanged(): void {\n        this._configChangedObservable.next()\n    }\n\n    private _notifyConfigurationError(err: Error): void {\n        this._configErrorObservable.next(err)\n    }\n\n    private _getLatestConfig(): void {\n        this._lastError = null\n\n        let userRuntimeConfig: Partial<IConfigurationValues> | null = null\n        let error: Error | null = null\n        if (fs.existsSync(this._configurationFilePath)) {\n            try {\n                const configurationContent = fs.readFileSync(this._configurationFilePath, \"utf-8\")\n                const script = new vm.Script(configurationContent, {\n                    filename: __filename,\n                })\n\n                const windowAsAny = window as any\n                const sandbox = {\n                    console,\n                    __filename,\n                    __dirname,\n                    module: {} as any,\n                    require: (str: string) => {\n                        const val = windowAsAny.require(str)\n                        return val\n                    },\n                    exports: {},\n                }\n                const context = vm.createContext(sandbox)\n                script.runInContext(context)\n\n                const exports = sandbox.module\n                    ? sandbox.module.exports || sandbox.exports\n                    : sandbox.exports\n\n                userRuntimeConfig = promoteConfigurationToRootLevel(exports)\n            } catch (e) {\n                e.message =\n                    \"[Config Error] Failed to parse \" +\n                    this._configurationFilePath +\n                    \":\\n\" +\n                    (e as Error).message\n                error = e\n\n                this._lastError = e\n                this._notifyConfigurationError(e)\n            }\n        }\n\n        if (!error) {\n            // If the configuration is null, but it had some value at some point,\n            // we assume this is due to reading while the file write is still\n            // in transition, and ignore it\n            if (userRuntimeConfig === null && this._configEverHadValue) {\n                Log.info(\"Configuraiton was null; skipping\")\n                return\n            }\n\n            if (isError(userRuntimeConfig)) {\n                Log.error(userRuntimeConfig)\n                return\n            }\n\n            if (userRuntimeConfig) {\n                this._configEverHadValue = true\n                this._latestConfiguration = userRuntimeConfig\n                this._notifyConfigurationChanged()\n            }\n        }\n    }\n}\n\nexport const promoteConfigurationToRootLevel = (\n    config: Partial<IConfigurationValues>,\n): Partial<IConfigurationValues> => {\n    if (config.configuration) {\n        const configurationValues = config.configuration\n        let mergedConfig = { ...config }\n        delete mergedConfig.configuration\n        mergedConfig = { ...mergedConfig, ...configurationValues }\n        return mergedConfig\n    }\n\n    return config\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/IConfigurationValues.ts",
    "content": "/**\n * IConfigurationValues\n * - Set of configuration values that Oni relies on\n *\n * NOTE: This may not be the complete set of configuration values,\n * because dependent packages or plugins may have their own set of configuration\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { TokenColor } from \"./../TokenColors\"\n\nexport type FontSmoothingOptions = \"auto\" | \"antialiased\" | \"subpixel-antialiased\" | \"none\"\nexport type DetectionSettings = \"always\" | \"noworkspace\" | \"never\"\n\nexport interface IConfigurationValues {\n    activate?: (oni: Oni.Plugin.Api) => void\n    deactivate?: () => void\n\n    // Debug settings\n    \"debug.fixedSize\": {\n        rows: number\n        columns: number\n    } | null\n\n    // Option to override neovim path. Used for testing new versions before bringing them in.\n    \"debug.neovimPath\": string | null\n\n    \"debug.persistOnNeovimExit\": boolean\n    \"debug.detailedSessionLogging\": boolean\n    \"debug.showTypingPrediction\": boolean\n\n    \"browser.defaultUrl\": string\n\n    // Simulate slow language server, for debugging\n    \"debug.fakeLag.languageServer\": number | null\n    \"debug.fakeLag.neovimInput\": number | null\n\n    \"debug.showNotificationOnError\": boolean\n\n    \"editor.split.mode\": string\n\n    \"configuration.editor\": string\n    \"configuration.showReferenceBuffer\": boolean\n\n    // - textMateHighlighting\n    \"editor.textMateHighlighting.enabled\": boolean\n\n    // Whether or not the learning pane is available\n    \"experimental.particles.enabled\": boolean\n    // Whether or not the sessions sidebar pane is enabled\n    \"experimental.sessions.enabled\": boolean\n    // A User specified directory for where Oni session files should be saved\n    \"experimental.sessions.directory\": string\n    // Whether Version control sidebar item is enabled\n    \"experimental.vcs.sidebar\": boolean\n    // Whether the color highlight layer is enabled\n    \"experimental.colorHighlight.enabled\": boolean\n    // Whitelist of extension for the color highlight layer\n    \"experimental.colorHighlight.filetypes\": string[]\n    // Whether the indent lines should be shown\n    \"experimental.indentLines.enabled\": boolean\n    // Whether or not to skip the first line of indentation\n    \"experimental.indentLines.skipFirst\": boolean\n    \"experimental.indentLines.color\": string\n    // Filetypes the indent lines are not shown for\n    \"experimental.indentLines.bannedFiletypes\": string[]\n    // Whether or not the vcs blame layer is enabled\n    \"experimental.vcs.blame.enabled\": boolean\n    // Whether or not the blame shows up automatically following a timeout or is manually\n    // triggered\n    \"experimental.vcs.blame.mode\": \"auto\" | \"manual\"\n    // Amount of millisenconds to delay before showing blame per line\n    \"experimental.vcs.blame.timeout\": number\n    // Whether the markdown preview pane should be shown\n    \"experimental.markdownPreview.enabled\": boolean\n    \"experimental.markdownPreview.autoScroll\": boolean\n    \"experimental.markdownPreview.syntaxHighlights\": boolean\n    \"experimental.markdownPreview.syntaxTheme\": string\n\n    // The transport to use for Neovim\n    // Valid values are \"stdio\" and \"pipe\"\n    \"experimental.neovim.transport\": string\n    \"wildmenu.mode\": boolean\n    \"commandline.mode\": boolean\n    \"commandline.icons\": boolean\n\n    // Experimental flag for 'generalized preview'\n    \"experimental.preview.enabled\": boolean\n\n    \"experimental.welcome.enabled\": boolean\n\n    \"autoClosingPairs.enabled\": boolean\n    \"autoClosingPairs.default\": any\n\n    // Production settings\n\n    // Bell sound effect to use\n    // See `:help bell` for instances where the bell sound would be used\n    \"oni.audio.bellUrl\": string\n\n    \"autoUpdate.enabled\": boolean\n\n    // Set this to `true` to enable additional syntax highlighting\n    // from Oni & language integrations\n    \"oni.enhancedSyntaxHighlighting\": boolean\n\n    // The default config is an opinionated, prescribed set of plugins. This is on by default to provide\n    // a good out-of-box experience, but will likely conflict with a Vim/Neovim veteran's finely honed config.\n    //\n    // Set this to 'false' to avoid loading the default config, and load settings from init.vim instead.\n    \"oni.useDefaultConfig\": boolean\n\n    // This string represents the path to the shell that the user would like oni to use to extract\n    // environment variables that it uses derives the $PATH variable from.\n    \"oni.userShell\": string\n\n    // By default, user's init.vim is not loaded, to avoid conflicts.\n    // Set this to `true` to enable loading of init.vim.\n    // Set this to a string to override the init.vim path.\n    \"oni.loadInitVim\": string | boolean\n\n    // If true, hide Menu bar by default\n    // (can still be activated by pressing 'Alt')\n    // If hidden, menu bar is hidden entirely.\n    \"oni.hideMenu\": boolean | \"hidden\"\n\n    // glob pattern of files to exclude from fuzzy finder (Ctrl-P)\n    \"oni.exclude\": string[]\n\n    // bookmarks to open if opened in install dir\n    \"oni.bookmarks\": string[]\n\n    // Editor settings\n\n    // Setting this to \"webgl\" switches to the experimental\n    // WebGL-based renderer. Please be aware that this might\n    // lead to instability or unexpected behavior until it is\n    // considered stable.\n    \"editor.renderer\": \"canvas\" | \"webgl\"\n\n    \"editor.backgroundOpacity\": number\n    \"editor.backgroundImageUrl\": string\n    \"editor.backgroundImageSize\": string\n\n    // Setting this to true enables yank integration with Oni\n    // When true, and text is yanked / deleted, that text will\n    // automatically be put on the clipboard.\n    //\n    // In addition, this enables <C-v> and <Cmd-v> behavior\n    // in paste from clipboard in insert mode.\n    \"editor.clipboard.enabled\": boolean\n\n    // When true (default), and `editor.clipboard.enabled` is `true`,\n    // yanks will be sent to the clipboard.\n    \"editor.clipboard.synchronizeYank\": boolean\n\n    // When true (not default), and `editor.clipboard.enabled` is `true`,\n    // deletes will be sent to the clipboard.\n    \"editor.clipboard.synchronizeDelete\": boolean\n\n    // Whether the 'go-to definition' language feature is enabled\n    \"editor.definition.enabled\": boolean\n\n    \"editor.quickInfo.enabled\": boolean\n    // Delay (in ms) for showing QuickInfo, when the cursor is on a term\n    \"editor.quickInfo.delay\": number\n    \"editor.quickOpen.defaultOpenMode\": Oni.FileOpenMode\n    \"editor.quickOpen.alternativeOpenMode\": Oni.FileOpenMode\n    \"editor.quickOpen.showHidden\": boolean\n\n    // this is new command to replace the above legacy editor prefixed command\n    \"quickOpen.defaultOpenMode\": Oni.FileOpenMode\n\n    \"editor.errors.slideOnFocus\": boolean\n    \"editor.formatting.formatOnSwitchToNormalMode\": boolean // TODO: Make this setting reliable. If formatting is slow, it will hose edits... not fun\n\n    // Sets the `popupmenu_external` option in Neovim\n    // Valid options are \"oni\", \"native\" or \"hidden\",\n    // where \"oni\" uses the Oni stylised Popups,\n    // \"native\" uses the default Vim ones,\n    // and \"hidden\" disables the automatic pop-ups, but keeps the stylised tabs when invoked.\n    //\n    // This will override the default UI to show a consistent popupmenu,\n    // whether using Oni's completion mechanisms or VIMs\n    //\n    // Use caution when changing the `menuopt` parameters if using\n    // a custom init.vim, as that may cause problematic behavior\n    \"editor.completions.mode\": string\n\n    // If true (default), ligatures are enabled\n    \"editor.fontLigatures\": boolean\n    \"editor.fontSize\": string\n    \"editor.fontWeight\": string\n    \"editor.fontFamily\": string // Platform specific\n\n    // Additional padding between lines\n    \"editor.linePadding\": number\n\n    // Maximum supported file size (by lines)\n    // to include language services/completion/syntax highlight/etc\n    \"editor.maxLinesForLanguageServices\": 2500\n\n    // If true (default), the buffer scroll bar will be visible\n    \"editor.scrollBar.visible\": boolean\n\n    // If true (default), the cursor tick will be shown in the scrollbar.\n    \"editor.scrollBar.cursorTick.visible\": boolean\n\n    // Allow overriding token colors for specific textmate scopes\n    \"editor.tokenColors\": TokenColor[]\n\n    // Additional paths to include when launching sub-process from Oni\n    // (and available in terminal integration, later)\n    \"environment.additionalPaths\": string[]\n\n    // Additional environment variables that override the default settings\n    \"environment.additionalVariables\": any\n\n    // User configurable array of files for which\n    // the image layer opens\n    \"editor.imageLayerExtensions\": string[]\n    // Command to list files for 'quick open'\n    // For example, to use 'ag': ag --nocolor -l .\n    //\n    // The command must emit a list of filenames\n    //\n    // IE, Windows:\n    // \"editor.quickOpen.execCommand\": \"dir /s /b\"\n    \"editor.quickOpen.execCommand\": string | null\n\n    // The filter strategy to use for processing results\n    // Options:\n    // - 'fuse' - use the fusejs strategy\n    // - 'regex' - use a regex based strategy\n    \"editor.quickOpen.filterStrategy\": string\n\n    // Typing prediction is Oni's implementation of\n    // 'zero-latency' mode typing, and increases responsiveness.\n    \"editor.typingPrediction\": boolean\n\n    // Files deleted in the explorer can be persisted for the duration\n    // of the session meaning that deletion can be undone is this is set\n    // to true\n    \"explorer.persistDeletedFiles\": boolean\n    \"explorer.maxUndoFileSizeInBytes\": number\n\n    \"editor.fullScreenOnStart\": boolean\n    \"editor.maximizeScreenOnStart\": boolean\n\n    \"editor.cursorLine\": boolean\n    \"editor.cursorLineOpacity\": number\n\n    \"editor.cursorColumn\": boolean\n    \"editor.cursorColumnOpacity\": number\n\n    \"keyDisplayer.showInInsertMode\": boolean\n\n    \"learning.enabled\": boolean\n    \"achievements.enabled\": boolean\n\n    // Case-sensitivity strategy for menu filtering:\n    // - if `true`, is case sensitive\n    // - if `false`, is not case sensitive\n    // - if `'smart'`, is case sensitive if the query string\n    //   contains uppercase characters\n    \"menu.caseSensitive\": string | boolean\n    \"menu.rowHeight\": number\n    \"menu.maxItemsToShow\": number\n\n    \"notifications.enabled\": boolean\n\n    // Output path to save screenshots and recordings\n    \"recorder.outputPath\": string\n\n    // If this is set to true, the recorder\n    // will save screenshots to clipboard instead\n    // of saving to file\n    \"recorder.copyScreenshotToClipboard\": boolean\n\n    \"sidebar.enabled\": boolean\n    \"sidebar.default.open\": boolean\n    \"sidebar.width\": string\n\n    \"sidebar.marks.enabled\": boolean\n    \"sidebar.plugins.enabled\": boolean\n\n    \"oni.plugins.prettier\": {\n        settings: {\n            semi: boolean\n            tabWidth: number\n            useTabs: boolean\n            singleQuote: boolean\n            trailingComma: \"es5\" | \"all\" | \"none\"\n            bracketSpacing: boolean\n            jsxBracketSameLine: boolean\n            arrowParens: \"avoid\" | \"always\"\n            printWidth: number\n            [key: string]: number | string | boolean\n        }\n        formatOnSave: boolean\n        enabled: boolean\n        allowedFiletypes?: string[]\n    }\n\n    \"snippets.enabled\": boolean\n    \"snippets.userSnippetFolder\": string\n\n    \"statusbar.enabled\": boolean\n    \"statusbar.fontSize\": string\n\n    \"statusbar.priority\": {\n        \"oni.status.filetype\": number\n        \"oni.status.workingDirectory\": number\n        \"oni.status.git\": number\n        \"oni.status.gitHubRepo\": number\n        \"oni.status.linenumber\": number\n        \"oni.status.mode\": number\n    }\n\n    \"tabs.mode\": string\n\n    // Height of individual tabs in the tab strip\n    \"tabs.height\": string\n\n    // Whether or not to render a highlight on the top of the tab\n    // (mode highlight)\n    \"tabs.highlight\": boolean\n\n    // Maximum width of a tab\n    \"tabs.maxWidth\": string\n\n    // Whether or not to show the index alongside the tab\n    \"tabs.showIndex\": boolean\n\n    // Whether or not tabs should wrap.\n    // If `false`, a scrollbar will be shown.\n    // If `true`, will wrap the tabs.\n    \"tabs.wrap\": boolean\n\n    // Whether or not the file icon\n    // should be shown in the tab\n    \"tabs.showFileIcon\": boolean\n\n    // can be anything the a css color property accepts e.g.:\n    // \"red\", \"#112233\", \"rgb(11,22,33)\"\n    \"tabs.dirtyMarker.userColor\": string\n\n    \"terminal.shellCommand\": string\n\n    \"ui.animations.enabled\": boolean\n    \"ui.iconTheme\": string\n    \"ui.colorscheme\": string\n    \"ui.fontFamily\": string\n    \"ui.fontSize\": string\n    \"ui.fontSmoothing\": FontSmoothingOptions\n\n    // Path to the default workspace. The default workspace\n    // will be opened if no workspace is specified in configuration.\n    \"workspace.defaultWorkspace\": string\n    \"workspace.autoDetectWorkspace\": DetectionSettings\n    \"workspace.autoDetectRootFiles\": string[]\n\n    // Handle other, non-predefined configuration keys\n    [configurationKey: string]: any\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/PersistentSettings.ts",
    "content": "/**\n * Persisted Settings\n *\n * Simple wrapper around 'electron-settings'\n */\n\nimport { remote } from \"electron\"\n\n// We need to use the 'main process' version of electron-settings.\n// See: https://github.com/nathanbuchar/electron-settings/wiki/FAQs\nconst PersistentSettings = remote.require(\"electron-settings\")\n\nimport { GenericConfigurationValues, IPersistedConfiguration } from \"./Configuration\"\n\nexport const get = <T>(key: string): T => {\n    return PersistentSettings.get(key) as T\n}\n\nexport const set = <T>(key: string, val: T): void => {\n    return PersistentSettings.set(key, val)\n}\n\nconst PersistedConfigurationKey: string = \"_internal.persistedConfiguration\"\n\nexport class PersistedConfiguration implements IPersistedConfiguration {\n    public getPersistedValues(): GenericConfigurationValues {\n        return get<GenericConfigurationValues>(PersistedConfigurationKey)\n    }\n\n    public setPersistedValues(configurationValues: GenericConfigurationValues): void {\n        const currentValues = this.getPersistedValues()\n\n        const combinedValues = {\n            ...currentValues,\n            ...configurationValues,\n        }\n\n        set(PersistedConfigurationKey, combinedValues)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/ReasonConfiguration.ts",
    "content": "/**\n * ReasonConfiguration.ts\n *\n * Settings for ocaml / reason language server\n */\n\nimport * as path from \"path\"\n\nimport * as Platform from \"./../../Platform\"\n\nexport const ocamlLanguageServerPath = path.join(\n    __dirname,\n    \"node_modules\",\n    \"ocaml-language-server\",\n    \"bin\",\n    \"server\",\n    \"index.js\",\n)\n\n// If Windows, wrap in `bash -ic` to support WSL\nconst wrapCommand = Platform.isWindows() ? (str: string) => \"bash -ic \" + str : (str: string) => str\n\nexport const ocamlAndReasonConfiguration = {\n    reason: {\n        codelens: {\n            enabled: true,\n            unicode: true,\n        },\n        bsb: {\n            enabled: true,\n        },\n        debounce: {\n            linter: 500,\n        },\n        diagnostics: {\n            tools: [\"bsb\", \"merlin\"],\n        },\n        path: {\n            bsb: wrapCommand(\"bsb\"),\n            ocamlfind: wrapCommand(\"ocamlfind\"),\n            ocamlmerlin: wrapCommand(\"ocamlmerlin\"),\n            opam: wrapCommand(\"opam\"),\n            rebuild: wrapCommand(\"rebuild\"),\n            refmt: wrapCommand(\"refmt\"),\n            refmterr: wrapCommand(\"refmterr\"),\n            rtop: wrapCommand(\"rtop\"),\n        },\n    },\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/UserConfiguration.ts",
    "content": "/**\n * UserConfiguration.ts\n *\n * Helpers and settings relating to per-user configuration\n */\n\nimport * as path from \"path\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as Platform from \"./../../Platform\"\n\nexport const getUserConfigFilePath = (): string => {\n    const configFileFromEnv = process.env[\"ONI_CONFIG_FILE\"] as string // tslint:disable-line\n\n    if (configFileFromEnv) {\n        Log.info(\n            \"getUserConfigFilePath - path overridden by environment variable:  \" +\n                configFileFromEnv,\n        )\n        return configFileFromEnv\n    }\n\n    return path.join(getUserConfigFolderPath(), \"config.js\")\n}\n\nexport const getUserConfigFolderPath = (): string => {\n    const configFileFromEnv = process.env[\"ONI_CONFIG_FILE\"] as string // tslint:disable-line\n    Log.info(\"$env:ONI_CONFIG_FILE: \" + configFileFromEnv)\n\n    if (configFileFromEnv) {\n        const configDir = path.dirname(configFileFromEnv)\n        Log.info(\"getUserConfigFolderPath - path overridden by environment variable:  \" + configDir)\n        return configDir\n    }\n\n    return Platform.isWindows()\n        ? path.join(Platform.getUserHome(), \"oni\")\n        : path.join(Platform.getUserHome(), \".config/oni\") // XDG-compliant\n}\n"
  },
  {
    "path": "browser/src/Services/Configuration/index.ts",
    "content": "export * from \"./Configuration\"\nexport * from \"./IConfigurationValues\"\nexport * from \"./UserConfiguration\"\n"
  },
  {
    "path": "browser/src/Services/ContextMenu/ContextMenu.tsx",
    "content": "/**\n * Menu.ts\n *\n * Implements API surface area for working with the status bar\n */\n\nimport * as React from \"react\"\nimport { bindActionCreators, Store } from \"redux\"\nimport thunk from \"redux-thunk\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { IToolTipsProvider } from \"./../../Editor/NeovimEditor/ToolTipsProvider\"\nimport { createStore } from \"./../../Redux\"\n\nimport * as ActionCreators from \"./../Menu/MenuActionCreators\"\nimport { createReducer } from \"./../Menu/MenuReducer\"\nimport * as State from \"./../Menu/MenuState\"\n\nimport { ContextMenuContainer } from \"./ContextMenuComponent\"\n\n// TODO: Remove filtering from the context menu responsibility\nconst reducer = createReducer<types.CompletionItem, types.CompletionItem>()\nconst noopFilter = (opts: types.CompletionItem[], searchText: string): types.CompletionItem[] =>\n    opts\n\n// TODO: This is essentially a duplicate of `MenuManager.ts` - can this be consolidated?\n// Can potentially move to a higher-order class that takes contextMenuActions/store as arguments\nexport type ContextMenuState = State.IMenus<types.CompletionItem, types.CompletionItem>\n\nexport class ContextMenuManager {\n    private _id: number = 0\n\n    private _store: Store<ContextMenuState>\n    private _actions: typeof ActionCreators\n\n    constructor(private _toolTips: IToolTipsProvider) {\n        this._store = createStore(\"CONTEXT-MENU\", reducer, State.createDefaultState(), [thunk])\n        this._actions = bindActionCreators(ActionCreators as any, this._store.dispatch)\n    }\n\n    public create(): ContextMenu {\n        this._id++\n        return new ContextMenu(this._id.toString(), this._store, this._actions, this._toolTips)\n    }\n\n    public isMenuOpen(): boolean {\n        return !!this._store.getState().menu\n    }\n\n    public nextMenuItem(): void {\n        this._actions.nextMenuItem()\n    }\n\n    public previousMenuItem(): void {\n        this._actions.previousMenuItem()\n    }\n\n    public closeActiveMenu(): void {\n        this._actions.hidePopupMenu()\n    }\n\n    public selectMenuItem(idx?: number): void {\n        const contextMenuState = this._store.getState()\n\n        if (contextMenuState && contextMenuState.menu) {\n            contextMenuState.menu.onSelectItem(idx)\n        }\n    }\n}\n\nexport class ContextMenu {\n    private _onItemSelected = new Event<any>()\n    private _onFilterTextChanged = new Event<string>()\n    private _onHide = new Event<void>()\n    private _onSelectedItemChanged = new Event<any>()\n\n    private _lastItems: any = null\n\n    public get onHide(): IEvent<void> {\n        return this._onHide\n    }\n\n    public get onItemSelected(): IEvent<any> {\n        return this._onItemSelected\n    }\n\n    public get onSelectedItemChanged(): IEvent<any> {\n        return this._onSelectedItemChanged\n    }\n\n    public get onFilterTextChanged(): IEvent<string> {\n        return this._onFilterTextChanged\n    }\n\n    public get selectedItem() {\n        return this._getSelectedItem()\n    }\n\n    constructor(\n        private _id: string,\n        private _store: Store<State.IMenus<types.CompletionItem, types.CompletionItem>>,\n        private _actions: typeof ActionCreators,\n        private _toolTips: IToolTipsProvider,\n    ) {}\n\n    public isOpen(): boolean {\n        const contextMenuState = this._store.getState()\n        return contextMenuState.menu && contextMenuState.menu.id === this._id\n    }\n\n    public setFilter(filter: string): void {\n        const contextMenuState = this._store.getState()\n\n        if (contextMenuState.menu && contextMenuState.menu.filter !== filter) {\n            this._actions.filterMenu(filter)\n        }\n    }\n\n    public setLoading(isLoading: boolean): void {\n        this._actions.setMenuLoading(this._id, isLoading)\n    }\n\n    public setItems(items: Oni.Menu.MenuOption[]): void {\n        if (items === this._lastItems) {\n            return\n        }\n\n        this._lastItems = items\n\n        this._actions.setMenuItems(this._id, items)\n    }\n\n    public show(items?: any[], filter?: string): void {\n        this._actions.showPopupMenu(\n            this._id,\n            {\n                filterFunction: noopFilter,\n                onSelectedItemChanged: (item: any) => this._onSelectedItemChanged.dispatch(item),\n                onSelectItem: (idx: number) => this._onItemSelectedHandler(idx),\n                onHide: () => this._onHidden(),\n                onFilterTextChanged: (newText: string) =>\n                    this._onFilterTextChanged.dispatch(newText),\n            } as any,\n            items,\n            filter,\n        )\n\n        this._toolTips.showToolTip(\n            this._getContextMenuId(),\n            <ContextMenuContainer store={this._store} />,\n            {\n                openDirection: 2,\n                position: null,\n                padding: \"0px\",\n            },\n        )\n    }\n\n    public hide(): void {\n        this._actions.hidePopupMenu()\n    }\n\n    private _onItemSelectedHandler(idx?: number): void {\n        const selectedOption = this._getSelectedItem(idx)\n        this._onItemSelected.dispatch(selectedOption)\n\n        this.hide()\n    }\n\n    private _getSelectedItem(idx?: number) {\n        const contextMenuState = this._store.getState()\n\n        if (!contextMenuState.menu) {\n            return null\n        }\n\n        const index = typeof idx === \"number\" ? idx : contextMenuState.menu.selectedIndex\n\n        return contextMenuState.menu.filteredOptions[index]\n    }\n\n    private _onHidden(): void {\n        this._toolTips.hideToolTip(this._getContextMenuId())\n        this._onHide.dispatch()\n    }\n\n    private _getContextMenuId(): string {\n        return \"context_menu_\" + this._id.toString()\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/ContextMenu/ContextMenuComponent.tsx",
    "content": "/**\n * ContextMenu.tsx\n */\n\nimport * as React from \"react\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { connect, Provider } from \"react-redux\"\nimport { Store } from \"redux\"\n\nimport * as Oni from \"oni-api\"\n\nimport { IMenus } from \"./../Menu/MenuState\"\n\nimport { Arrow, ArrowDirection } from \"./../../UI/components/Arrow\"\nimport styled, { enableMouse, layer } from \"./../../UI/components/common\"\nimport { HighlightText } from \"./../../UI/components/HighlightText\"\nimport { QuickInfoDocumentation } from \"./../../UI/components/QuickInfo\"\nimport { Icon } from \"./../../UI/Icon\"\n\nimport { ContextMenuState } from \"./ContextMenu\"\n\nexport interface IContextMenuItem {\n    label: string\n    detail?: string\n    documentation?: string | types.MarkupContent\n    icon?: string\n}\n\nconst Autocompletion = styled.div`\n    ${layer};\n    ${enableMouse};\n    width: 600px;\n    overflow: hidden;\n    animation-name: appear;\n    animation-duration: 0.1s;\n`\n\nexport interface IContextMenuProps {\n    visible: boolean\n    base: string\n    entries: IContextMenuItem[]\n    selectedIndex: number\n}\n\nexport const ContextMenuView: React.SFC<IContextMenuProps> = props => {\n    if (!props.visible) {\n        return null\n    }\n\n    let entriesToRender: IContextMenuItem[] = []\n    let { selectedIndex: adjustedIndex } = props\n\n    // TODO: sync max display items (10) with value in Reducer.autoCompletionReducer() (Reducer.ts)\n    if (adjustedIndex < 10) {\n        entriesToRender = props.entries.slice(0, 10)\n    } else {\n        entriesToRender = props.entries.slice(adjustedIndex - 9, adjustedIndex + 1)\n        adjustedIndex = entriesToRender.length - 1\n    }\n\n    const entries = entriesToRender.map((entry, index) => {\n        const isSelected = index === adjustedIndex\n\n        return (\n            <ContextMenuItem\n                {...entry}\n                key={`${index}-${entry.detail}`}\n                isSelected={isSelected}\n                base={props.base}\n            />\n        )\n    })\n\n    const selectedItemDocumentation = getDocumentationFromItems(entriesToRender, adjustedIndex)\n    return (\n        <Autocompletion data-id=\"autocompletion\">\n            {entries}\n            <ContextMenuDocumentation documentation={selectedItemDocumentation} />\n        </Autocompletion>\n    )\n}\n\nconst getDocumentationFromItems = (items: any[], selectedIndex: number): string => {\n    if (!items || !items.length) {\n        return null\n    }\n\n    if (selectedIndex < 0 || selectedIndex >= items.length) {\n        return null\n    }\n\n    return items[selectedIndex].documentation\n}\n\nexport const Label = styled(HighlightText)`\n    flex: 1 0 auto;\n    min-width: 100px;\n    margin-left: 8px;\n`\n\nconst Highlight = styled.span`\n    text-decoration: underline;\n`\n\ninterface ISelectedProps {\n    isSelected: boolean\n}\n\nconst Entry = styled<ISelectedProps, \"div\">(\"div\")`\n    ${({ isSelected }) =>\n        isSelected &&\n        `transform: translateY(0.1px);\n         box-shadow: 0 1px 8px 1px rgba(0, 0, 0, 0.2), 0 1px 20px 0 rgba(0, 0, 0, 0.19);\n    `};\n`\n\nconst Main = styled<ISelectedProps, \"div\">(\"div\")`\n    transition: opacity 1s;\n    opacity: ${props => (props.isSelected ? \"1\" : \"0.8\")};\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n`\n\nconst IconWrapper = styled.div`\n    padding: 4px;\n    width: 1.2em;\n    flex: 0 0 auto;\n    text-align: center;\n    background-color: ${({ theme }) => theme[\"contextMenu.highlight\"]};\n    i {\n        font-size: 0.9em;\n    }\n`\n\nexport const Detail = styled<ISelectedProps, \"div\">(\"div\")`\n    flex: 0 1 auto;\n    min-width: 50px;\n    text-align: right;\n    text-overflow: ellipsis;\n    overflow: hidden;\n    white-space: nowrap;\n    margin: 0 5px 0 16px;\n    font-size: 0.8em;\n    opacity: 0.8;\n    visibility: hidden;\n    ${props => (props.isSelected ? \"visibility:visible;\" : \"\")};\n`\n\nexport interface IContextMenuItemProps extends Oni.Menu.MenuOption, ISelectedProps {\n    base: string\n}\n\nexport const ContextMenuItem: React.SFC<IContextMenuItemProps> = props => {\n    const { isSelected, label, icon, base, detail } = props\n\n    return (\n        <Entry isSelected={isSelected} key={label}>\n            <Main isSelected={isSelected}>\n                <IconWrapper>\n                    <Icon name={icon} />\n                </IconWrapper>\n                <Arrow direction={ArrowDirection.Right} size={5} isSelected={isSelected} />\n                <Label highlightComponent={Highlight} highlightText={base} text={label} />\n                <Detail isSelected={isSelected}>{detail}</Detail>\n            </Main>\n        </Entry>\n    )\n}\n\nexport interface IContextMenuDocumentationProps {\n    documentation: string\n}\n\nexport const ContextMenuDocumentation = ({ documentation }: IContextMenuDocumentationProps) => {\n    return documentation ? <QuickInfoDocumentation text={documentation} /> : null\n}\n\ntype IState = IMenus<types.CompletionItem, types.CompletionItem>\n\nconst mapStateToProps = ({ menu: contextMenu }: IState): IContextMenuProps => {\n    if (!contextMenu) {\n        return {\n            visible: false,\n            base: \"\",\n            entries: [] as IContextMenuItem[],\n            selectedIndex: 0,\n        } as IContextMenuProps\n    }\n    return {\n        visible: true,\n        base: contextMenu.filter,\n        entries: contextMenu.filteredOptions,\n        selectedIndex: contextMenu.selectedIndex,\n    }\n}\n\nexport const ConnectedContextMenu = connect(mapStateToProps)(ContextMenuView)\n\nexport const ContextMenuContainer = (props: { store: Store<ContextMenuState> }) => {\n    return (\n        <Provider store={props.store}>\n            <ConnectedContextMenu />\n        </Provider>\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/ContextMenu/index.ts",
    "content": "export * from \"./ContextMenu\"\nexport * from \"./ContextMenuComponent\"\n"
  },
  {
    "path": "browser/src/Services/Debug.ts",
    "content": "/**\n * Debug.ts\n *\n * A set of commands used for debugging\n */\n\nimport { remote } from \"electron\"\n\nimport { CommandManager } from \"./CommandManager\"\nimport {\n    AchievementsManager,\n    getInstance as getAchievementsInstance,\n} from \"./Learning/Achievements\"\n\nexport const activate = (commandManager: CommandManager) => {\n    const openDevTools = () => {\n        remote.getCurrentWindow().webContents.openDevTools()\n        const achievements = getAchievementsInstance()\n        achievements.notifyGoal(\"oni.goal.openDevTools\")\n    }\n\n    commandManager.registerCommand({\n        command: \"oni.debug.openDevTools\",\n        name: \"Debug: Open Developer Tools\",\n        detail: \"Debug Oni and any running plugins, using the Chromium developer tools\",\n        execute: () => openDevTools(),\n    })\n\n    commandManager.registerCommand({\n        command: \"oni.debug.reload\",\n        name: \"Debug: Reload Oni\",\n        detail: \"Reloads the Oni instance. You will lose all unsaved changes!\",\n        execute: () => remote.getCurrentWindow().reload(),\n    })\n}\n\nexport const registerAchievements = (achievements: AchievementsManager) => {\n    achievements.registerAchievement({\n        uniqueId: \"oni.achievement.openDevTools.1\",\n        name: \"Pop the Hood\",\n        description: \"Open the 'Developer Tools' for the first time\",\n        goals: [\n            {\n                name: null,\n                goalId: \"oni.goal.openDevTools\",\n                count: 1,\n            },\n        ],\n    })\n\n    achievements.registerAchievement({\n        uniqueId: \"oni.achievement.openDevTools.2\",\n        dependsOnId: \"oni.achievement.openDevTools.1\",\n        name: \"Mechanic\",\n        description: \"Open the 'Developer Tools' ten times.\",\n        goals: [\n            {\n                name: null,\n                goalId: \"oni.goal.openDevTools\",\n                count: 10,\n            },\n        ],\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Diagnostics/index.ts",
    "content": "/**\n * Diagnostics/index.ts\n *\n * Integrates the `textDocument/publishDiagnostics` protocol with Oni's UI\n */\n\nimport * as flatten from \"lodash/flatten\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { ILanguageServerNotificationResponse, LanguageManager } from \"../Language\"\n\nimport * as Helpers from \"../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport * as Utility from \"../../Utility\"\n\ninterface IPublishDiagnosticsParams {\n    uri: string\n    diagnostics: types.Diagnostic[]\n}\n\nexport interface Errors {\n    [file: string]: { [key: string]: types.Diagnostic[] }\n}\n\nexport interface IDiagnosticsDataSource {\n    onErrorsChanged: IEvent<void>\n\n    getErrors(): Errors\n\n    setErrors(filePath: string, key: string, errors: types.Diagnostic[]): void\n    getErrorsForPosition(filePath: string, line: number, column: number): types.Diagnostic[]\n\n    start(languageManager: LanguageManager): void\n}\n\nexport const getColorFromSeverity = (severity: types.DiagnosticSeverity): string => {\n    switch (severity) {\n        case types.DiagnosticSeverity.Error:\n            return \"red\"\n        case types.DiagnosticSeverity.Warning:\n            return \"yellow\"\n        case types.DiagnosticSeverity.Information:\n        case types.DiagnosticSeverity.Hint:\n        default:\n            return \"gray\"\n    }\n}\n\nexport const getAllErrorsForFile = (fileName: string, errors: Errors): types.Diagnostic[] => {\n    if (!fileName || !errors) {\n        return Utility.EmptyArray\n    }\n\n    const allErrorsByKey = errors[fileName]\n\n    if (!allErrorsByKey) {\n        return Utility.EmptyArray\n    }\n\n    const arrayOfErrorsArray = Object.values(allErrorsByKey)\n    return flatten(arrayOfErrorsArray)\n}\n\nexport class DiagnosticsDataSource {\n    private _errors: Errors = {}\n    private _onErrorsChangedEvent = new Event<void>()\n\n    public get onErrorsChanged(): IEvent<void> {\n        return this._onErrorsChangedEvent\n    }\n\n    public setErrors(filePath: string, key: string, errors: types.Diagnostic[]): void {\n        filePath = Utility.normalizePath(filePath)\n        const currentFile = this._errors[filePath] || null\n\n        this._errors = {\n            ...this._errors,\n            [filePath]: {\n                ...currentFile,\n                [key]: [...errors],\n            },\n        }\n\n        this._onErrorsChangedEvent.dispatch()\n    }\n\n    public getErrors(): Errors {\n        return this._errors\n    }\n\n    public getErrorsForPosition(\n        filePath: string,\n        line: number,\n        column: number,\n    ): types.Diagnostic[] {\n        const errors = getAllErrorsForFile(Utility.normalizePath(filePath), this._errors)\n\n        return errors.filter(diagnostic => {\n            return Utility.isInRange(line, column, diagnostic.range)\n        })\n    }\n\n    public start(languageManager: LanguageManager): void {\n        languageManager.subscribeToLanguageServerNotification(\n            \"textDocument/publishDiagnostics\",\n            (args: ILanguageServerNotificationResponse) => {\n                const test = args.payload as IPublishDiagnosticsParams\n\n                const file = Helpers.unwrapFileUriPath(test.uri)\n                const key = \"language-\" + args.language\n\n                this.setErrors(file, key, test.diagnostics)\n            },\n        )\n    }\n}\n\nlet _diagnostics: DiagnosticsDataSource = null\n\nexport const getInstance = (): IDiagnosticsDataSource => {\n    if (!_diagnostics) {\n        _diagnostics = new DiagnosticsDataSource()\n    }\n\n    return _diagnostics\n}\n"
  },
  {
    "path": "browser/src/Services/Diagnostics/navigateErrors.ts",
    "content": "/**\n * navigateErrors.ts\n *\n * Functions to jump to previous/next diagnostic error in the active buffer\n */\nimport { isInRange } from \"./../../Utility\"\nimport { getAllErrorsForFile, getInstance as getDiagnosticsInstance } from \"./../Diagnostics\"\nimport { editorManager } from \"./../EditorManager\"\n\nexport const gotoNextError = async () => {\n    const errors = getDiagnosticsInstance().getErrors()\n    const activeBuffer = editorManager.activeEditor.activeBuffer\n    const currentFileErrors = getAllErrorsForFile(activeBuffer.filePath, errors)\n    const currentPosition = activeBuffer.cursor\n\n    if (!currentFileErrors || !currentFileErrors.length) {\n        return\n    }\n\n    for (const error of currentFileErrors) {\n        if (isInRange(currentPosition.line, currentPosition.column, error.range)) {\n            continue\n        }\n\n        const currentLine = (await activeBuffer.getLines(currentPosition.line))[0]\n        if (\n            currentPosition.line === error.range.start.line &&\n            currentLine.length <= error.range.start.character\n        ) {\n            continue\n        }\n\n        if (\n            error.range.start.line > currentPosition.line ||\n            (error.range.start.line === currentPosition.line &&\n                error.range.start.character > currentPosition.column)\n        ) {\n            await activeBuffer.setCursorPosition(\n                error.range.start.line,\n                error.range.start.character,\n            )\n            return\n        }\n    }\n\n    await activeBuffer.setCursorPosition(\n        currentFileErrors[0].range.start.line,\n        currentFileErrors[0].range.start.character,\n    )\n}\n\nexport const gotoPreviousError = async () => {\n    const errors = getDiagnosticsInstance().getErrors()\n    const activeBuffer = editorManager.activeEditor.activeBuffer\n    const currentFileErrors = getAllErrorsForFile(activeBuffer.filePath, errors)\n    const currentPosition = activeBuffer.cursor\n\n    if (!currentFileErrors || !currentFileErrors.length) {\n        return\n    }\n\n    let lastError = currentFileErrors[currentFileErrors.length - 1]\n    for (const error of currentFileErrors) {\n        if (\n            isInRange(currentPosition.line, currentPosition.column, error.range) ||\n            error.range.start.line > currentPosition.line ||\n            (error.range.start.line === currentPosition.line &&\n                error.range.start.character > currentPosition.column)\n        ) {\n            await activeBuffer.setCursorPosition(\n                lastError.range.start.line,\n                lastError.range.start.character,\n            )\n            return\n        }\n        lastError = error\n    }\n\n    await activeBuffer.setCursorPosition(\n        lastError.range.start.line,\n        lastError.range.start.character,\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/DragAndDrop.tsx",
    "content": "import * as React from \"react\"\nimport * as DND from \"react-dnd\"\n\ntype Render<T> = (props: T) => React.ReactElement<T>\ntype OnDrop = (item: any) => object | void\ntype IsValidDrop = (item: any) => boolean\n\n// Drop Target ================================================================\nexport interface IDroppeable {\n    isOver?: boolean\n    connectDropTarget?: any\n    onDrop: OnDrop\n    isValidDrop: IsValidDrop\n    canDrop?: boolean\n    didDrop?: boolean\n    accepts: string[] | string\n    render: Render<{\n        canDrop: boolean\n        isOver?: boolean\n        didDrop?: boolean\n        connectDropTarget?: DND.DropTargetConnector\n    }>\n}\ninterface DroppedProps {\n    onDrop: OnDrop\n    isValidDrop: IsValidDrop\n}\n\nconst DropTarget = {\n    drop(dropped: DroppedProps, monitor: DND.DropTargetMonitor) {\n        return dropped.onDrop({ drag: monitor.getItem(), drop: dropped })\n    },\n    canDrop(props: DroppedProps, monitor: DND.DropTargetMonitor) {\n        return props.isValidDrop({ drag: monitor.getItem(), drop: props })\n    },\n}\n\nconst DropCollect = (connect: DND.DropTargetConnector, monitor: DND.DropTargetMonitor) => ({\n    connectDropTarget: connect.dropTarget(),\n    isOver: monitor.isOver(),\n    canDrop: monitor.canDrop(),\n    didDrop: monitor.didDrop(),\n})\n\n/**\n * A component which can have items of a specific matching type dropped onto it\n */\n@DND.DropTarget<IDroppeable>(({ accepts }) => accepts, DropTarget, DropCollect)\nexport class Droppeable<P extends IDroppeable> extends React.Component<P> {\n    public render() {\n        const { isOver, connectDropTarget, canDrop, didDrop } = this.props\n        return connectDropTarget(<div>{this.props.render({ isOver, canDrop, didDrop })}</div>)\n    }\n}\n\n// Drag Source ================================================================\nexport interface IDraggeable {\n    target?: string\n    isDragging?: boolean\n    connectDragSource?: any\n    render: Render<{ isDragging?: boolean; connectDragSource?: DND.DragSourceConnector }>\n}\n\nconst DragSource = {\n    beginDrag(props: object) {\n        return props\n    },\n}\n\nconst DragCollect = (connect: DND.DragSourceConnector, monitor: DND.DragSourceMonitor) => {\n    return {\n        connectDragSource: connect.dragSource(),\n        isDragging: monitor.isDragging(),\n    }\n}\n\n/**\n * A component that can be dragged onto a droppeable one\n *\n * @name props\n * @function\n * @param {String | String[]} props.target The target Type that responds to the drop\n * @param {Object} DragSource Object with a beginDrag which return the dragged props\n * @param {React.Component} A component which is dragged onto another\n * @returns {React.Component<P>} A react class component\n */\n@DND.DragSource<IDraggeable>(props => props.target, DragSource, DragCollect)\nexport class Draggeable<P extends IDraggeable> extends React.Component<P> {\n    public render() {\n        const { isDragging, connectDragSource } = this.props\n        return connectDragSource(<div>{this.props.render({ isDragging })}</div>)\n    }\n}\n\ninterface IDragDrop {\n    isOver?: boolean\n    didDrop?: boolean\n    onDrop: OnDrop\n    accepts: string[] | string\n    connectDropTarget?: any\n    canDrop?: boolean\n    isValidDrop: IsValidDrop\n    dragTarget: string\n    isDragging?: boolean\n    connectDragSource?: any\n    render: Render<{ didDrop?: boolean; canDrop?: boolean; isOver?: boolean; isDragging?: boolean }>\n}\n\n/**\n * A render prop which takes a given component and makes it a drop target as well as draggeable\n */\n@DND.DropTarget<IDragDrop>(props => props.accepts, DropTarget, DropCollect)\n@DND.DragSource<IDragDrop>(props => props.dragTarget, DragSource, DragCollect)\nexport class DragAndDrop<P extends IDragDrop> extends React.Component<P> {\n    public render() {\n        const { connectDragSource, connectDropTarget } = this.props\n\n        return connectDropTarget(connectDragSource(<div>{this.props.render(this.props)}</div>))\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/EditorManager.ts",
    "content": "/**\n * EditorManager.ts\n *\n * Responsible for managing state of the editor collection, and\n * switching between active editors.\n *\n * It also provides convenience methods for hooking events\n * to the active editor, and managing transitions between editors.\n */\n\nimport * as Oni from \"oni-api\"\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { remote } from \"electron\"\n\nexport class EditorManager implements Oni.EditorManager {\n    private _allEditors: Oni.Editor[] = []\n    private _activeEditor: Oni.Editor = null\n    private _anyEditorProxy: AnyEditorProxy = new AnyEditorProxy()\n    private _onActiveEditorChanged: Event<Oni.Editor> = new Event<Oni.Editor>()\n\n    private _closeWhenNoEditors: boolean = true\n\n    public get allEditors(): Oni.Editor[] {\n        return this._allEditors\n    }\n\n    /**\n     * API Methods\n     */\n    public get anyEditor(): Oni.Editor {\n        return this._anyEditorProxy\n    }\n\n    public get activeEditor(): Oni.Editor {\n        return this._activeEditor\n    }\n\n    public get onActiveEditorChanged(): IEvent<Oni.Editor> {\n        return this._onActiveEditorChanged\n    }\n\n    public openFile(\n        filePath: string,\n        openOptions: Oni.FileOpenOptions = Oni.DefaultFileOpenOptions,\n    ): Promise<Oni.Buffer> {\n        return this._activeEditor.openFile(filePath, openOptions)\n    }\n\n    public setCloseWhenNoEditors(closeWhenNoEditors: boolean) {\n        this._closeWhenNoEditors = closeWhenNoEditors\n    }\n\n    public registerEditor(editor: Oni.Editor) {\n        if (this._allEditors.indexOf(editor) === -1) {\n            this._allEditors.push(editor)\n        }\n    }\n\n    public unregisterEditor(editor: Oni.Editor): void {\n        this._allEditors = this._allEditors.filter(ed => ed !== editor)\n\n        if (this._activeEditor === editor) {\n            this.setActiveEditor(null)\n        }\n\n        if (this._allEditors.length === 0 && this._closeWhenNoEditors) {\n            // Quit?\n            remote.getCurrentWindow().close()\n        }\n    }\n\n    /**\n     * Internal Methods\n     */\n    public setActiveEditor(editor: Oni.Editor) {\n        this._activeEditor = editor\n\n        const oldEditor = this._anyEditorProxy.getUnderlyingEditor()\n        if (editor !== oldEditor) {\n            this._onActiveEditorChanged.dispatch(editor)\n            this._anyEditorProxy.setActiveEditor(editor)\n        }\n    }\n}\n\n/**\n * AllEditors is a proxy for the Neovim interface,\n * exposing methods of 'all' editors, as an aggregate.\n *\n * This enables consumers to use `Oni.editor.allEditors.onModeChanged((newMode) => { ... }),\n * for convenience, as it handles manages tracking subscriptions as the active editor changes.\n */\nclass AnyEditorProxy implements Oni.Editor {\n    private _activeEditor: Oni.Editor\n    private _subscriptions: IDisposable[] = []\n\n    private _onModeChanged = new Event<Oni.Vim.Mode>()\n    private _onBufferEnter = new Event<Oni.EditorBufferEventArgs>()\n    private _onBufferLeave = new Event<Oni.EditorBufferEventArgs>()\n    private _onBufferChanged = new Event<Oni.EditorBufferChangedEventArgs>()\n    private _onBufferSaved = new Event<Oni.EditorBufferEventArgs>()\n    private _onBufferScrolled = new Event<Oni.EditorBufferScrolledEventArgs>()\n    private _onCursorMoved = new Event<Oni.Cursor>()\n\n    /**\n     * API Methods\n     */\n    public get mode(): string {\n        if (!this._activeEditor) {\n            return null\n        }\n\n        return this._activeEditor.mode\n    }\n\n    public get activeBuffer(): Oni.Buffer {\n        // TODO: Replace with null-object pattern\n        if (!this._activeEditor) {\n            return null\n        }\n\n        return this._activeEditor.activeBuffer\n    }\n\n    public init(filesToOpen: string[]): void {\n        if (!this._activeEditor) {\n            return\n        }\n\n        this._activeEditor.init(filesToOpen)\n    }\n\n    public get neovim(): Oni.NeovimEditorCapability {\n        if (!this._activeEditor) {\n            return null\n        }\n\n        return this._activeEditor.neovim\n    }\n\n    public get onModeChanged(): IEvent<Oni.Vim.Mode> {\n        return this._onModeChanged\n    }\n\n    public get onBufferChanged(): IEvent<Oni.EditorBufferChangedEventArgs> {\n        return this._onBufferChanged\n    }\n\n    public get onBufferEnter(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._onBufferEnter\n    }\n\n    public get onBufferLeave(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._onBufferLeave\n    }\n\n    public get onBufferSaved(): IEvent<Oni.EditorBufferEventArgs> {\n        return this._onBufferSaved\n    }\n\n    public get onBufferScrolled(): IEvent<Oni.EditorBufferScrolledEventArgs> {\n        return this._onBufferScrolled\n    }\n\n    public get onCursorMoved(): IEvent<Oni.Cursor> {\n        return this._onCursorMoved\n    }\n\n    public dispose(): void {\n        // tslint:disable-line\n    }\n\n    public async blockInput(\n        inputFunction: (input: Oni.InputCallbackFunction) => Promise<void>,\n    ): Promise<void> {\n        return this._activeEditor.blockInput(inputFunction)\n    }\n\n    public async openFile(filePath: string, openOptions: Oni.FileOpenOptions): Promise<Oni.Buffer> {\n        return this._activeEditor.openFile(filePath, openOptions)\n    }\n\n    public getBuffers(): Array<Oni.Buffer | Oni.InactiveBuffer> {\n        return this._activeEditor.getBuffers()\n    }\n\n    public setTextOptions(options: Oni.EditorTextOptions): Promise<void> {\n        return this._activeEditor.setTextOptions(options)\n    }\n\n    public render(): JSX.Element {\n        if (!this._activeEditor) {\n            return null\n        }\n\n        return this._activeEditor.render()\n    }\n\n    public setSelection(selectionRange: types.Range): Promise<void> {\n        if (!this._activeEditor) {\n            return null\n        }\n\n        return this._activeEditor.setSelection(selectionRange)\n    }\n\n    /**\n     * Internal methods\n     */\n\n    public setActiveEditor(newEditor: Oni.Editor) {\n        this._activeEditor = newEditor\n\n        this._subscriptions.forEach(d => d.dispose())\n\n        if (!newEditor) {\n            return\n        }\n\n        this._subscriptions = [\n            newEditor.onModeChanged.subscribe(val => this._onModeChanged.dispatch(val)),\n            newEditor.onBufferEnter.subscribe(val => this._onBufferEnter.dispatch(val)),\n            newEditor.onBufferLeave.subscribe(val => this._onBufferLeave.dispatch(val)),\n            newEditor.onBufferChanged.subscribe(val => this._onBufferChanged.dispatch(val)),\n            newEditor.onBufferSaved.subscribe(val => this._onBufferSaved.dispatch(val)),\n            newEditor.onBufferScrolled.subscribe(val => this._onBufferScrolled.dispatch(val)),\n            newEditor.onCursorMoved.subscribe(val => this._onCursorMoved.dispatch(val)),\n        ]\n    }\n\n    public getUnderlyingEditor(): Oni.Editor {\n        return this._activeEditor\n    }\n}\n\nexport const editorManager: EditorManager = new EditorManager()\n"
  },
  {
    "path": "browser/src/Services/Explorer/ExplorerFileSystem.ts",
    "content": "/**\n * ExplorerFileSystem.ts\n *\n * State management for the explorer split\n */\n\nimport * as fs from \"fs\"\nimport { ensureDirSync, mkdirp, move, pathExists, remove, writeFile } from \"fs-extra\"\nimport * as os from \"os\"\nimport * as path from \"path\"\nimport { promisify } from \"util\"\n\nimport { FolderOrFile } from \"./ExplorerStore\"\n\n/**\n * An abstraction of the node filesystem APIs to enable testing\n */\nexport interface IFileSystem {\n    readdir(fullPath: string): Promise<FolderOrFile[]>\n    exists(fullPath: string): Promise<boolean>\n    realpath(fullPath: string): Promise<string>\n    persistNode(fullPath: string): Promise<void>\n    restoreNode(fullPath: string): Promise<void>\n    deleteNode(fullPath: string): Promise<void>\n    canPersistNode(fullPath: string, size: number): Promise<boolean>\n    move(source: string, dest: string): Promise<void>\n    moveNodesBack(collection: Array<{ source: string; destination: string }>): Promise<void>\n    writeFile(filepath: string): Promise<void>\n    mkdir(folderpath: string): Promise<void>\n}\n\nexport class FileSystem implements IFileSystem {\n    private _fs: {\n        readdir(path: string): Promise<string[]>\n        stat(path: string): Promise<fs.Stats>\n        exists(path: string): Promise<boolean>\n        realpath(path: string): Promise<string>\n    }\n\n    private _backupDirectory = path.join(os.tmpdir(), \"oni_backup\")\n\n    public get backupDir(): string {\n        return this._backupDirectory\n    }\n\n    constructor(nfs: typeof fs) {\n        this._fs = {\n            readdir: promisify(nfs.readdir.bind(nfs)),\n            stat: promisify(nfs.stat.bind(nfs)),\n            exists: promisify(nfs.exists.bind(nfs)),\n            realpath: promisify(nfs.realpath.bind(nfs)),\n        }\n\n        this.init()\n    }\n\n    public init = () => {\n        ensureDirSync(this._backupDirectory)\n    }\n\n    public async readdir(directoryPath: string): Promise<FolderOrFile[]> {\n        const files = await this._fs.readdir(directoryPath)\n\n        const filesAndFolders = files.map(async f => {\n            const fullPath = path.join(directoryPath, f)\n            const isDirectory = await this._fs\n                .stat(fullPath)\n                .then(stat => stat.isDirectory())\n                .catch(() => false)\n            if (isDirectory) {\n                return {\n                    type: \"folder\",\n                    fullPath,\n                } as FolderOrFile\n            } else {\n                return {\n                    type: \"file\",\n                    fullPath,\n                } as FolderOrFile\n            }\n        })\n\n        return Promise.all(filesAndFolders)\n    }\n\n    public exists(fullPath: string): Promise<boolean> {\n        return this._fs.exists(fullPath)\n    }\n\n    /**\n     * Resolve symlinks in a path to give the real absolute path.\n     */\n    public realpath(fullPath: string): Promise<string> {\n        return this._fs.realpath(fullPath)\n    }\n\n    /**\n     * Delete a file or Folder\n     *\n     * @name deleteNode\n     * @function\n     * @param {ExplorerNode} node The file or folder node\n     */\n    public async deleteNode(fullPath: string): Promise<void> {\n        await remove(fullPath)\n    }\n\n    /**\n     * Move a file or folder from the backup dir to its original location\n     *\n     * @name restoreNode\n     * @function\n     * @param {string} fileOrFolder The file or folder path\n     */\n    public restoreNode = async (prevPath: string): Promise<void> => {\n        const name = path.basename(prevPath)\n        const backupPath = path.join(this._backupDirectory, name)\n        await move(backupPath, prevPath)\n    }\n\n    public move = async (source: string, dest: string): Promise<void> => {\n        return this.areDifferent(source, dest) && move(source, dest)\n    }\n    /**\n     * Saves a file to the tmp directory to persist deleted files\n     *\n     * @name PersistNode\n     * @function\n     * @param {string} filename A file or folder path\n     */\n    public persistNode = async (fileOrFolder: string): Promise<void> => {\n        const { size } = await this._fs.stat(fileOrFolder)\n        const hasEnoughSpace = os.freemem() > size\n        if (hasEnoughSpace) {\n            const filename = path.basename(fileOrFolder)\n            const newPath = path.join(this._backupDirectory, filename)\n            await move(fileOrFolder, newPath, { overwrite: true })\n        }\n    }\n\n    /**\n     * Moves an array of files and folders to their original locations\n     *\n     * @name moveNodesBack\n     * @function\n     * @param {Array} collection An array of object with a file/folder and its destination folder\n     * @returns {void}\n     */\n    public moveNodesBack = async (\n        collection: Array<{ destination: string; source: string }>,\n    ): Promise<void> => {\n        await Promise.all(\n            collection.map(\n                async ({ source, destination }) =>\n                    this.areDifferent(source, destination) && move(destination, source),\n            ),\n        )\n    }\n\n    /**\n     * canPersistNode\n     * Determine based on size whether the directory should be persisted\n     */\n    public canPersistNode = async (fullPath: string, maxSize: number): Promise<boolean> => {\n        const { size } = await this._fs.stat(fullPath)\n        return size < maxSize\n    }\n\n    /**\n     * createFile\n     */\n    public async writeFile(filepath: string) {\n        if (await pathExists(filepath)) {\n            throw new Error(\"This path already exists\")\n        }\n        await writeFile(filepath, \"\", null)\n    }\n\n    public async mkdir(folderpath: string) {\n        if (await pathExists(folderpath)) {\n            throw new Error(\"This path already exists\")\n        }\n        await mkdirp(folderpath)\n    }\n\n    private areDifferent = (src: string, dest: string) => src !== dest\n}\n\nexport const OniFileSystem = new FileSystem(fs)\n"
  },
  {
    "path": "browser/src/Services/Explorer/ExplorerSelectors.ts",
    "content": "/**\n * ExplorerSelectors.ts\n *\n * Selectors for the explorer state\n */\n\nimport * as path from \"path\"\n\nimport * as flatten from \"lodash/flatten\"\n\nimport { ExpandedFolders, FolderOrFile, IExplorerState } from \"./ExplorerStore\"\n\nexport interface IContainerNode {\n    id: string\n    type: \"container\"\n    expanded: boolean\n    name: string\n}\n\nexport interface IFolderNode {\n    id: string\n    type: \"folder\"\n    folderPath: string\n    expanded: boolean\n    name: string\n    indentationLevel: number\n}\n\nexport interface IFileNode {\n    id: string\n    type: \"file\"\n    filePath: string\n    modified: boolean\n    name: string\n    indentationLevel: number\n}\n\nexport const EmptyNode: ExplorerNode = {\n    type: null,\n    id: null,\n    modified: null,\n    filePath: null,\n    name: null,\n    indentationLevel: null,\n}\n\nexport type ExplorerNode = IContainerNode | IFolderNode | IFileNode\n\nexport const isPathExpanded = (state: IExplorerState, pathToCheck: string): boolean => {\n    return !!state.expandedFolders[pathToCheck]\n}\n\nexport const mapStateToNodeList = (state: IExplorerState): ExplorerNode[] => {\n    let ret: ExplorerNode[] = []\n\n    //     ret.push({\n    //         id: \"opened\",\n    //         type: \"container\",\n    //         expanded: true,\n    //         name: \"Opened Files\",\n    //     })\n\n    //     const openedFiles: ExplorerNode[] = Object.keys(state.openedFiles)\n    //         .filter(filePath => !!filePath)\n    //         .map(filePath => ({\n    //         type: \"file\",\n    //         id: \"opened:\" + filePath,\n    //         filePath,\n    //         name: path.basename(filePath),\n    //         modified: false, // TODO\n    //         indentationLevel: 0,\n    //     } as ExplorerNode))\n\n    //     ret = [...ret, ...openedFiles]\n\n    if (!state.rootFolder || !state.rootFolder.fullPath) {\n        return ret\n    }\n\n    ret.push({\n        id: \"explorer\",\n        type: \"container\",\n        expanded: !!state.expandedFolders[state.rootFolder.fullPath],\n        name: state.rootFolder.fullPath,\n    })\n\n    const expandedTree = flattenFolderTree(state.rootFolder, [], state.expandedFolders, 0)\n\n    // The root node is included in the output, so we'll remove it\n    const [, ...remainingTree] = expandedTree\n\n    ret = [...ret, ...remainingTree]\n    return ret\n}\n\nexport const flattenFolderTree = (\n    folderTree: FolderOrFile,\n    currentList: ExplorerNode[],\n    expandedFolders: ExpandedFolders,\n    indentationLevel: number,\n): ExplorerNode[] => {\n    switch (folderTree.type) {\n        case \"file\":\n            const file: ExplorerNode = {\n                type: \"file\",\n                name: path.basename(folderTree.fullPath),\n                id: \"explorer:\" + folderTree.fullPath,\n                filePath: folderTree.fullPath,\n                modified: false,\n                indentationLevel,\n            }\n            return [...currentList, file]\n        case \"folder\":\n            const expanded = !!expandedFolders[folderTree.fullPath]\n\n            const folder: ExplorerNode = {\n                type: \"folder\",\n                id: \"explorer:\" + folderTree.fullPath,\n                folderPath: folderTree.fullPath,\n                name: path.basename(folderTree.fullPath),\n                expanded,\n                indentationLevel,\n            }\n\n            const folderChildren = expandedFolders[folderTree.fullPath] || []\n            const children = flatten(\n                folderChildren.map(c =>\n                    flattenFolderTree(c, [], expandedFolders, indentationLevel + 1),\n                ),\n            )\n\n            return [...currentList, folder, ...children]\n        default:\n            return []\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Explorer/ExplorerSplit.tsx",
    "content": "/**\n * ExplorerSplit.tsx\n *\n */\n\nimport * as path from \"path\"\nimport * as React from \"react\"\nimport { Provider } from \"react-redux\"\nimport { Store } from \"redux\"\nimport { FileSystemWatcher } from \"./../../Services/FileSystemWatcher\"\n\nimport * as Oni from \"oni-api\"\nimport { Event } from \"oni-types\"\n\nimport { CallbackCommand } from \"./../../Services/CommandManager\" // TODO: Discuss: Move to API?\nimport { getInstance as NotificationsInstance } from \"./../../Services/Notifications\"\nimport { windowManager } from \"./../../Services/WindowManager\"\n\nimport { createStore, getPathForNode, IExplorerState } from \"./ExplorerStore\"\n\nimport * as ExplorerSelectors from \"./ExplorerSelectors\"\nimport { Explorer } from \"./ExplorerView\"\n\ntype Node = ExplorerSelectors.ExplorerNode\n\nexport class ExplorerSplit {\n    private _onEnterEvent: Event<void> = new Event<void>()\n    private _selectedId: string = null\n    private _store: Store<IExplorerState>\n    private _watcher: FileSystemWatcher = null\n\n    public get id(): string {\n        return \"oni.sidebar.explorer\"\n    }\n\n    public get title(): string {\n        return \"Explorer\"\n    }\n\n    constructor(private _oni: Oni.Plugin.Api) {\n        this._store = createStore({ notifications: NotificationsInstance() })\n\n        this._initializeFileSystemWatcher()\n\n        this._oni.workspace.onDirectoryChanged.subscribe(newDirectory => {\n            this._store.dispatch({\n                type: \"SET_ROOT_DIRECTORY\",\n                rootPath: newDirectory,\n            })\n\n            if (this._watcher) {\n                this._watcher.unwatch(this._oni.workspace.activeWorkspace)\n                this._watcher.watch(newDirectory)\n            }\n        })\n\n        if (this._oni.workspace.activeWorkspace) {\n            this._store.dispatch({\n                type: \"SET_ROOT_DIRECTORY\",\n                rootPath: this._oni.workspace.activeWorkspace,\n            })\n        }\n    }\n\n    public enter(): void {\n        this._store.dispatch({ type: \"ENTER\" })\n        this._initialiseExplorerCommands()\n        this._onEnterEvent.dispatch()\n    }\n\n    public leave(): void {\n        this._store.dispatch({ type: \"LEAVE\" })\n    }\n\n    public moveFileOrFolder = (source: Node, dest: Node): void => {\n        this._store.dispatch({ type: \"PASTE\", pasted: [source], target: dest })\n    }\n\n    public render(): JSX.Element {\n        return (\n            <Provider store={this._store}>\n                <Explorer\n                    onCancelCreate={this._cancelCreation}\n                    onCompleteCreate={this._completeCreation}\n                    onCompleteRename={this._completeRename}\n                    onCancelRename={this._cancelRename}\n                    onClick={id => this._onOpenItem(id)}\n                    moveFileOrFolder={this.moveFileOrFolder}\n                    onSelectionChanged={id => this._onSelectionChanged(id)}\n                />\n            </Provider>\n        )\n    }\n\n    public locateFile = (filePath: string) => {\n        this._store.dispatch({ type: \"SELECT_FILE\", filePath })\n    }\n\n    private _initializeFileSystemWatcher(): void {\n        if (this._oni.configuration.getValue(\"explorer.autoRefresh\")) {\n            this._watcher = new FileSystemWatcher({\n                target: this._oni.workspace.activeWorkspace,\n                options: { ignoreInitial: true, ignored: \"**/node_modules\" },\n            })\n\n            const events = [\"onChange\", \"onAdd\", \"onAddDir\", \"onMove\", \"onDelete\", \"onDeleteDir\"]\n            events.forEach(event => this._watcher[event].subscribe(() => this._refresh()))\n        }\n    }\n\n    private _inputInProgress = () => {\n        const {\n            register: { rename, create },\n        } = this._store.getState()\n        return rename.active || create.active\n    }\n\n    private _refresh(): void {\n        this._store.dispatch({ type: \"REFRESH\" })\n    }\n\n    private _initialiseExplorerCommands(): void {\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.delete.persist\",\n                null,\n                null,\n                () => !this._inputInProgress() && this._onDeleteItem({ persist: true }),\n            ),\n        )\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.delete\",\n                null,\n                null,\n                () => !this._inputInProgress() && this._onDeleteItem({ persist: false }),\n            ),\n        )\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.yank\",\n                \"Explorer: Yank Selected Item\",\n                \"Select a file to move\",\n                () => !this._inputInProgress() && this._onYankItem(),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.undo\",\n                \"Explorer: Undo Last Action\",\n                null,\n                () => !this._inputInProgress() && this._onUndoItem(),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.paste\",\n                \"Explorer: Move/Paste Selected Item\",\n                \"Paste the last yanked item\",\n                () => !this._inputInProgress() && this._onPasteItem(),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.refresh\",\n                \"Explorer: Refresh The Tree\",\n                \"Updates the explorer with the latest state on the file system\",\n                () => !this._inputInProgress() && this._refresh(),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.create.file\",\n                \"Explorer: Create A New File\",\n                null,\n                () => !this._inputInProgress() && this._onCreateNode({ type: \"file\" }),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.create.folder\",\n                \"Explorer: Create A New Directory\",\n                null,\n                () => !this._inputInProgress() && this._onCreateNode({ type: \"folder\" }),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.expand.directory\",\n                \"Explorer: Expand Selected Directory\",\n                null,\n                () => !this._inputInProgress() && this._toggleDirectory(\"expand\"),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.collapse.directory\",\n                \"Explorer: Collapse Selected Directory\",\n                null,\n                () => !this._inputInProgress() && this._toggleDirectory(\"collapse\"),\n            ),\n        )\n\n        this._oni.commands.registerCommand(\n            new CallbackCommand(\n                \"explorer.rename\",\n                \"Explorer: Rename Selected File/Folder\",\n                null,\n                () => !this._inputInProgress() && this._renameItem(),\n            ),\n        )\n    }\n\n    private _onSelectionChanged(id: string): void {\n        this._selectedId = id\n        // If we are trying to select a file, check if it's now selected, and if so trigger success.\n        const fileToSelect: string = this._store.getState().fileToSelect\n        if (fileToSelect) {\n            const selectedPath: string = getPathForNode(this._getSelectedItem())\n            if (selectedPath === fileToSelect) {\n                this._store.dispatch({ type: \"SELECT_FILE_SUCCESS\" })\n            }\n        }\n    }\n\n    private _onOpenItem(id?: string): void {\n        const selectedItem = this._getSelectedItem(id)\n\n        if (!selectedItem) {\n            return\n        }\n\n        const state = this._store.getState()\n\n        switch (selectedItem.type) {\n            case \"file\":\n                this._oni.editors.activeEditor.openFile(selectedItem.filePath)\n                // FIXME: the editor manager is not a windowSplit aka this\n                // Should be being called with an ID not an active editor\n                windowManager.focusSplit(\"oni.window.0\")\n                return\n            case \"container\":\n            case \"folder\":\n                const directoryPath =\n                    selectedItem.type === \"container\" ? selectedItem.name : selectedItem.folderPath\n                const isDirectoryExpanded = ExplorerSelectors.isPathExpanded(state, directoryPath)\n                this._store.dispatch({\n                    type: isDirectoryExpanded ? \"COLLAPSE_DIRECTORY\" : \"EXPAND_DIRECTORY\",\n                    directoryPath,\n                })\n                return\n        }\n    }\n\n    private _getSelectedItem(id: string = this._selectedId): ExplorerSelectors.ExplorerNode {\n        const state = this._store.getState()\n\n        const nodes = ExplorerSelectors.mapStateToNodeList(state)\n\n        const items = nodes.filter(item => item.id === id)\n\n        if (!items || !items.length) {\n            return null\n        }\n\n        return items[0]\n    }\n\n    private _getSelectedItemParent(filePath: string): ExplorerSelectors.ExplorerNode {\n        const state = this._store.getState()\n        const nodes = ExplorerSelectors.mapStateToNodeList(state)\n        const parentDir = path.dirname(filePath)\n\n        const [parentNode] = nodes.filter(\n            item =>\n                (item.type === \"folder\" && item.folderPath === parentDir) ||\n                (item.type === \"container\" && item.name === parentDir),\n        )\n\n        return parentNode\n    }\n\n    private _renameItem = () => {\n        const selected = this._getSelectedItem()\n        if (!selected) {\n            return\n        }\n        this._store.dispatch({ type: \"RENAME_START\", target: selected })\n    }\n\n    private _completeRename = (newName: string) => {\n        const target = this._getSelectedItem()\n\n        if (!target) {\n            return\n        }\n        this._store.dispatch({ type: \"RENAME_COMMIT\", newName, target })\n    }\n\n    private _cancelRename = () => {\n        this._store.dispatch({ type: \"RENAME_CANCEL\" })\n    }\n\n    private _onCreateNode = ({ type }: { type: \"file\" | \"folder\" }) => {\n        this._store.dispatch({ type: \"CREATE_NODE_START\", nodeType: type })\n    }\n\n    private _completeCreation = (newName: string) => {\n        const target = this._getSelectedItem()\n\n        if (!target) {\n            return\n        }\n\n        const nodePath = getPathForNode(target)\n        const dirname = target.type === \"file\" ? path.dirname(nodePath) : nodePath\n        this._store.dispatch({ type: \"CREATE_NODE_COMMIT\", name: path.join(dirname, newName) })\n    }\n\n    private _cancelCreation = () => {\n        this._store.dispatch({ type: \"CREATE_NODE_CANCEL\" })\n    }\n\n    // This is different from on openItem since it only activates if the target is a folder\n    // also it means that each bound key only does one thing aka \"h\" collapses and \"l\"\n    // expands they are not toggles\n    private _toggleDirectory(action: \"expand\" | \"collapse\"): void {\n        const selectedItem = this._getSelectedItem()\n        if (!selectedItem || selectedItem.type !== \"folder\") {\n            return\n        }\n\n        const type = action === \"expand\" ? \"EXPAND_DIRECTORY\" : \"COLLAPSE_DIRECTORY\"\n        this._store.dispatch({ type, directoryPath: selectedItem.folderPath })\n    }\n\n    private _onUndoItem(): void {\n        const {\n            register: { undo },\n        } = this._store.getState()\n        if (undo.length) {\n            this._store.dispatch({ type: \"UNDO\" })\n        }\n    }\n\n    private _onYankItem(): void {\n        const selectedItem = this._getSelectedItem()\n        if (!selectedItem) {\n            return\n        }\n\n        const {\n            register: { yank },\n        } = this._store.getState()\n        const inYankRegister = yank.some(({ id }) => id === selectedItem.id)\n\n        if (!inYankRegister) {\n            this._store.dispatch({ type: \"YANK\", target: selectedItem })\n        } else {\n            this._store.dispatch({ type: \"CLEAR_REGISTER\", ids: [selectedItem.id] })\n        }\n    }\n\n    private _onPasteItem(): void {\n        const pasteTarget = this._getSelectedItem()\n        if (!pasteTarget) {\n            return\n        }\n\n        const {\n            register: { yank },\n        } = this._store.getState()\n\n        if (yank.length && pasteTarget) {\n            const sources = yank.map(\n                node => (node.type === \"file\" ? this._getSelectedItemParent(node.filePath) : node),\n            )\n            this._store.dispatch({\n                type: \"PASTE\",\n                target: pasteTarget,\n                pasted: yank,\n                sources,\n            })\n        }\n    }\n\n    private _onDeleteItem({ persist }: { persist: boolean }): void {\n        const selectedItem = this._getSelectedItem()\n\n        if (!selectedItem) {\n            return\n        }\n        this._store.dispatch({ type: \"DELETE\", target: selectedItem, persist })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Explorer/ExplorerStore.ts",
    "content": "/**\n * ExplorerStore.ts\n *\n * State management for the explorer split\n */\n\nimport * as capitalize from \"lodash/capitalize\"\nimport * as last from \"lodash/last\"\nimport * as omit from \"lodash/omit\"\nimport * as path from \"path\"\n\nimport { Reducer, Store } from \"redux\"\nimport { combineEpics, createEpicMiddleware, Epic } from \"redux-observable\"\n\nimport { forkJoin } from \"rxjs/observable/forkJoin\"\nimport { fromPromise } from \"rxjs/observable/fromPromise\"\nimport { timer } from \"rxjs/observable/timer\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { createStore as createReduxStore } from \"./../../Redux\"\nimport { configuration } from \"./../Configuration\"\nimport { EmptyNode, ExplorerNode } from \"./ExplorerSelectors\"\n\nimport { Notifications } from \"./../../Services/Notifications\"\nimport { NotificationLevel } from \"./../../Services/Notifications/NotificationStore\"\n\nimport { IFileSystem, OniFileSystem } from \"./ExplorerFileSystem\"\n\nexport interface IFolderState {\n    type: \"folder\"\n    fullPath: string\n}\n\nexport const DefaultFolderState: IFolderState = {\n    type: \"folder\",\n    fullPath: null,\n}\n\nexport const DefaultRegisterState: IRegisterState = {\n    yank: [],\n    undo: [],\n    paste: EmptyNode,\n    updated: null,\n    create: {\n        active: false,\n        name: null,\n        nodeType: null,\n    },\n    rename: {\n        active: false,\n        target: null,\n    },\n}\n\nexport interface IFileState {\n    type: \"file\"\n    fullPath: string\n}\n\nexport interface IRecentFile {\n    filePath: string\n    modified: boolean\n}\n\nexport type FolderOrFile = IFolderState | IFileState\n\nexport interface ExpandedFolders {\n    [fullPath: string]: FolderOrFile[]\n}\n\nexport interface OpenedFiles {\n    [fullPath: string]: any\n}\n\nexport type RegisterAction =\n    | IPasteAction\n    | IDeleteSuccessAction\n    | IDeleteFailAction\n    | IDeleteAction\n    | IUndoAction\n    | IUndoSuccessAction\n    | IUndoFailAction\n    | IRenameSuccessAction\n    | IRenameFailAction\n    | ICreateNodeSuccessAction\n    | ICreateNodeFailAction\n\ninterface IRegisterState {\n    yank: ExplorerNode[]\n    paste: ExplorerNode\n    undo: RegisterAction[]\n    rename: {\n        active: boolean\n        target: ExplorerNode\n    }\n    updated: string[]\n    create: {\n        active: boolean\n        name: string\n        nodeType: \"file\" | \"folder\"\n    }\n}\n\nexport interface IExplorerState {\n    // Open workspace\n    rootFolder: IFolderState\n\n    expandedFolders: ExpandedFolders\n    fileToSelect: string\n    hasFocus: boolean\n    register: IRegisterState\n}\n\nexport const DefaultExplorerState: IExplorerState = {\n    rootFolder: null,\n    expandedFolders: {},\n    fileToSelect: null,\n    hasFocus: false,\n    register: DefaultRegisterState,\n}\n\nexport interface IUndoAction {\n    type: \"UNDO\"\n}\n\nexport interface IUndoSuccessAction {\n    type: \"UNDO_SUCCESS\"\n}\n\nexport interface IUndoFailAction {\n    type: \"UNDO_FAIL\"\n    reason: string\n}\n\nexport interface IYankAction {\n    type: \"YANK\"\n    path: string\n    target: ExplorerNode\n}\n\nexport interface IPasteAction {\n    type: \"PASTE\"\n    target: ExplorerNode\n    pasted: ExplorerNode[]\n    sources: ExplorerNode[]\n}\n\nexport interface IDeleteAction {\n    type: \"DELETE\"\n    target: ExplorerNode\n    persist: boolean\n}\n\nexport interface IDeleteSuccessAction {\n    type: \"DELETE_SUCCESS\"\n    target: ExplorerNode\n    persist: boolean\n}\n\nexport interface IDeleteFailAction {\n    type: \"DELETE_FAIL\"\n    reason: string\n}\n\nexport interface IClearRegisterAction {\n    type: \"CLEAR_REGISTER\"\n    ids: string[]\n}\n\nexport interface IExpandDirectoryAction {\n    type: \"EXPAND_DIRECTORY\"\n    directoryPath: string\n}\n\nexport interface IRefreshAction {\n    type: \"REFRESH\"\n}\n\nexport interface ISetRootDirectoryAction {\n    type: \"SET_ROOT_DIRECTORY\"\n    rootPath: string\n}\n\nexport interface ICollapseDirectory {\n    type: \"COLLAPSE_DIRECTORY\"\n    directoryPath: string\n}\n\nexport interface IExpandDirectoryResult {\n    type: \"EXPAND_DIRECTORY_RESULT\"\n    directoryPath: string\n    children: FolderOrFile[]\n}\n\nexport interface ISelectFileAction {\n    type: \"SELECT_FILE\"\n    filePath: string\n}\n\nexport interface ISelectFilePendingAction {\n    type: \"SELECT_FILE_PENDING\"\n    filePath: string\n}\n\nexport interface ISelectFileSuccessAction {\n    type: \"SELECT_FILE_SUCCESS\"\n}\n\nexport interface ISelectFileFailAction {\n    type: \"SELECT_FILE_FAIL\"\n    reason: string\n}\n\nexport interface IEnterAction {\n    type: \"ENTER\"\n}\n\nexport interface ILeaveAction {\n    type: \"LEAVE\"\n}\n\nexport interface IPasteFailAction {\n    type: \"PASTE_FAIL\"\n    reason: string\n}\n\nexport interface IClearUpdateAction {\n    type: \"CLEAR_UPDATE\"\n}\n\nexport interface ICreateNodeStartAction {\n    type: \"CREATE_NODE_START\"\n    nodeType: \"file\" | \"folder\"\n}\n\nexport interface ICreateNodeCancelAction {\n    type: \"CREATE_NODE_CANCEL\"\n}\n\nexport interface ICreateNodeCommitAction {\n    type: \"CREATE_NODE_COMMIT\"\n    name: string\n}\n\nexport interface ICreateNodeFailAction {\n    type: \"CREATE_NODE_FAIL\"\n    reason: string\n}\n\nexport interface ICreateNodeSuccessAction {\n    type: \"CREATE_NODE_SUCCESS\"\n    nodeType: \"file\" | \"folder\"\n    name: string\n}\n\nexport interface IPasteSuccessAction {\n    type: \"PASTE_SUCCESS\"\n    moved: IMovedNodes[]\n}\n\nexport interface IRenameStartAction {\n    type: \"RENAME_START\"\n    target: ExplorerNode\n    active: boolean\n}\n\nexport interface IRenameSuccessAction {\n    type: \"RENAME_SUCCESS\"\n    source: string\n    destination: string\n    targetType: string\n}\n\nexport interface IRenameFailAction {\n    type: \"RENAME_FAIL\"\n    reason: string\n}\n\nexport interface ICancelRenameAction {\n    type: \"RENAME_CANCEL\"\n}\n\nexport interface IRenameCommitAction {\n    type: \"RENAME_COMMIT\"\n    target: ExplorerNode\n    newName: string\n}\n\nexport interface INotificationSentAction {\n    type: \"NOTIFICATION_SENT\"\n    typeOfNotification: string\n}\n\nexport interface IMovedNodes {\n    node: ExplorerNode\n    destination: string\n}\n\nexport type ExplorerAction =\n    | IEnterAction\n    | ILeaveAction\n    | IExpandDirectoryResult\n    | ICollapseDirectory\n    | ISetRootDirectoryAction\n    | IExpandDirectoryAction\n    | IRenameStartAction\n    | IRenameSuccessAction\n    | IRenameFailAction\n    | IRenameCommitAction\n    | ICancelRenameAction\n    | IDeleteFailAction\n    | IRefreshAction\n    | IDeleteAction\n    | IDeleteSuccessAction\n    | IYankAction\n    | IPasteAction\n    | IPasteFailAction\n    | IPasteSuccessAction\n    | IClearUpdateAction\n    | IClearRegisterAction\n    | IUndoAction\n    | IUndoSuccessAction\n    | IUndoFailAction\n    | ICreateNodeStartAction\n    | ICreateNodeFailAction\n    | ICreateNodeCancelAction\n    | ICreateNodeCommitAction\n    | ICreateNodeSuccessAction\n    | INotificationSentAction\n    | ISelectFileAction\n    | ISelectFilePendingAction\n    | ISelectFileSuccessAction\n    | ISelectFileFailAction\n\n// Helper functions for Updating state ========================================================\nexport const removePastedNode = (nodeArray: ExplorerNode[], ids: string[]): ExplorerNode[] =>\n    nodeArray.filter(node => !ids.includes(node.id))\n\nexport const removeUndoItem = (undoArray: RegisterAction[]): RegisterAction[] =>\n    undoArray.slice(0, undoArray.length - 1)\n\nconst getSourceAndDestPaths = (source: ExplorerNode, dest: ExplorerNode) => {\n    const sourcePath = getPathForNode(source)\n    const destPath = dest.type === \"file\" ? path.dirname(dest.filePath) : getPathForNode(dest)\n    const destination = path.join(destPath, path.basename(sourcePath))\n    return { source: sourcePath, destination }\n}\n\n// Do not add un-undoable action to the undo list\nexport const shouldAddDeletion = (action: IDeleteSuccessAction) => (action.persist ? [action] : [])\n\ntype Updates =\n    | IPasteSuccessAction\n    | IDeleteSuccessAction\n    | IUndoSuccessAction\n    | IRenameSuccessAction\n    | ICreateNodeSuccessAction\n\nexport const getUpdatedNode = (action: Updates, state?: IRegisterState): string[] => {\n    switch (action.type) {\n        case \"PASTE_SUCCESS\":\n            return action.moved.map(node => node.destination)\n        case \"DELETE_SUCCESS\":\n            return [getPathForNode(action.target)]\n        case \"RENAME_SUCCESS\":\n            return [action.destination]\n        case \"CREATE_NODE_SUCCESS\":\n            return [action.name]\n        case \"UNDO_SUCCESS\":\n            const lastAction = last(state.undo)\n\n            if (lastAction.type === \"DELETE_SUCCESS\") {\n                return [getPathForNode(lastAction.target)]\n            } else if (lastAction.type === \"PASTE\") {\n                return lastAction.pasted.map(node => getPathForNode(node))\n            } else if (lastAction.type === \"RENAME_SUCCESS\") {\n                return [lastAction.source]\n            }\n\n            return []\n        default:\n            return []\n    }\n}\n\nconst shouldExpandDirectory = (targets: ExplorerNode[]): IExpandDirectoryAction[] =>\n    targets\n        .map(target => target.type !== \"file\" && Actions.expandDirectory(getPathForNode(target)))\n        .filter(Boolean)\n\nexport const getPathForNode = (node: ExplorerNode) => {\n    if (!node) {\n        return null\n    } else if (node.type === \"file\") {\n        return node.filePath\n    } else if (node.type === \"folder\") {\n        return node.folderPath\n    } else {\n        return node.name\n    }\n}\n\n// Strongly typed actions/action-creators to be used in multiple epics\n\nconst Actions = {\n    Null: { type: null } as ExplorerAction,\n\n    createNode: (args: { nodeType: \"file\" | \"folder\"; name: string }) =>\n        ({ type: \"CREATE_NODE_SUCCESS\", ...args } as ICreateNodeSuccessAction),\n\n    createNodeFail: (reason: string) =>\n        ({ type: \"CREATE_NODE_FAIL\", reason } as ICreateNodeFailAction),\n\n    pasteSuccess: (moved: IMovedNodes[]) =>\n        ({ type: \"PASTE_SUCCESS\", moved } as IPasteSuccessAction),\n\n    pasteFail: (reason: string) => ({ type: \"PASTE_FAIL\", reason } as IPasteFailAction),\n\n    undoFail: (reason: string) => ({ type: \"UNDO_FAIL\", reason } as IUndoFailAction),\n\n    undoSuccess: { type: \"UNDO_SUCCESS\" } as IUndoSuccessAction,\n\n    renameSuccess: (args: {\n        source: string\n        destination: string\n        targetType: string\n    }): IRenameSuccessAction => ({\n        type: \"RENAME_SUCCESS\",\n        ...args,\n    }),\n\n    renameFail: (reason: string) => ({ type: \"RENAME_FAIL\", reason } as IRenameFailAction),\n\n    paste: { type: \"PASTE\" } as IPasteAction,\n\n    refresh: { type: \"REFRESH\" } as IRefreshAction,\n\n    deleteFail: (reason: string) => ({ type: \"DELETE_FAIL\", reason } as IDeleteFailAction),\n\n    clearRegister: (ids: string[]) => ({ type: \"CLEAR_REGISTER\", ids } as IClearRegisterAction),\n\n    clearUpdate: { type: \"CLEAR_UPDATE\" } as IClearUpdateAction,\n\n    deleteSuccess: (target: ExplorerNode, persist: boolean): IDeleteSuccessAction => ({\n        type: \"DELETE_SUCCESS\",\n        target,\n        persist,\n    }),\n\n    notificationSent: (typeOfNotification: string): INotificationSentAction => ({\n        type: \"NOTIFICATION_SENT\",\n        typeOfNotification,\n    }),\n\n    expandDirectory: (directoryPath: string): IExpandDirectoryAction => ({\n        type: \"EXPAND_DIRECTORY\",\n        directoryPath,\n    }),\n\n    expandDirectoryResult: (\n        pathToExpand: string,\n        sortedFilesAndFolders: FolderOrFile[],\n    ): ExplorerAction => {\n        return {\n            type: \"EXPAND_DIRECTORY_RESULT\",\n            directoryPath: pathToExpand,\n            children: sortedFilesAndFolders,\n        }\n    },\n\n    selectFile: (filePath: string): ISelectFileAction => ({\n        type: \"SELECT_FILE\",\n        filePath,\n    }),\n}\n\n// Yank, Paste Delete register =============================\n// The undo register is essentially a list of past actions\n// => [paste, delete, paste], when an action is carried out\n// it is added to the back of the stack when an undo is triggered\n// it is removed.\n// The most recently actioned node(s) path(s) are set to the value of\n// the updated field, this is used to animate updated fields,\n// Updates are cleared shortly after to prevent re-animating\n\nexport const yankRegisterReducer: Reducer<IRegisterState> = (\n    state: IRegisterState = DefaultRegisterState,\n    action: ExplorerAction,\n) => {\n    switch (action.type) {\n        case \"CREATE_NODE_START\":\n            return {\n                ...state,\n                create: {\n                    active: true,\n                    name: null,\n                    nodeType: action.nodeType,\n                },\n            }\n        case \"CREATE_NODE_FAIL\":\n        case \"CREATE_NODE_CANCEL\":\n            return {\n                ...state,\n                create: {\n                    active: false,\n                    name: null,\n                    nodeType: null,\n                },\n            }\n        case \"CREATE_NODE_SUCCESS\":\n            return {\n                ...state,\n                create: {\n                    active: false,\n                    name: null,\n                    nodeType: null,\n                },\n                updated: getUpdatedNode(action),\n                undo: [...state.undo, action],\n            }\n        case \"RENAME_START\":\n            return {\n                ...state,\n                rename: {\n                    active: true,\n                    target: action.target,\n                },\n            }\n        case \"RENAME_CANCEL\":\n            return {\n                ...state,\n                rename: {\n                    active: false,\n                    target: null,\n                },\n            }\n        case \"RENAME_SUCCESS\":\n            return {\n                ...state,\n                undo: [...state.undo, action],\n                updated: getUpdatedNode(action),\n                rename: {\n                    active: false,\n                    target: null,\n                },\n            }\n        case \"YANK\":\n            return {\n                ...state,\n                yank: [...state.yank, action.target],\n            }\n        case \"PASTE\":\n            return {\n                ...state,\n                paste: action.target,\n                undo: [...state.undo, action],\n            }\n        case \"PASTE_SUCCESS\":\n            return {\n                ...state,\n                updated: getUpdatedNode(action),\n            }\n        case \"UNDO_SUCCESS\":\n            return {\n                ...state,\n                undo: removeUndoItem(state.undo),\n                updated: getUpdatedNode(action, state),\n            }\n        case \"CLEAR_REGISTER\":\n            return {\n                ...state,\n                paste: EmptyNode,\n                yank: removePastedNode(state.yank, action.ids),\n            }\n        case \"CLEAR_UPDATE\":\n            return {\n                ...state,\n                updated: null,\n            }\n        case \"DELETE_SUCCESS\":\n            return {\n                ...state,\n                undo: [...state.undo, ...shouldAddDeletion(action)],\n                updated: getUpdatedNode(action),\n            }\n        case \"LEAVE\":\n            return { ...DefaultRegisterState, undo: state.undo }\n        case \"DELETE_FAIL\":\n        default:\n            return state\n    }\n}\n\nexport const rootFolderReducer: Reducer<IFolderState> = (\n    state: IFolderState = DefaultFolderState,\n    action: ExplorerAction,\n) => {\n    switch (action.type) {\n        case \"SET_ROOT_DIRECTORY\":\n            return {\n                ...state,\n                type: \"folder\",\n                fullPath: action.rootPath,\n            }\n\n        default:\n            return state\n    }\n}\n\nexport const expandedFolderReducer: Reducer<ExpandedFolders> = (\n    state: ExpandedFolders = {},\n    action: ExplorerAction,\n) => {\n    switch (action.type) {\n        case \"SET_ROOT_DIRECTORY\":\n            return {}\n        case \"COLLAPSE_DIRECTORY\":\n            return omit(state, [action.directoryPath])\n        case \"EXPAND_DIRECTORY_RESULT\":\n            return {\n                ...state,\n                [action.directoryPath]: action.children,\n            }\n        default:\n            return state\n    }\n}\n\nexport const hasFocusReducer: Reducer<boolean> = (\n    state: boolean = false,\n    action: ExplorerAction,\n) => {\n    switch (action.type) {\n        case \"ENTER\":\n            return true\n        case \"LEAVE\":\n            return false\n        default:\n            return state\n    }\n}\n\nexport const selectFileReducer: Reducer<string> = (\n    state: string = null,\n    action: ExplorerAction,\n) => {\n    switch (action.type) {\n        case \"SELECT_FILE_PENDING\":\n            return action.filePath\n        case \"SELECT_FILE_SUCCESS\":\n            return null\n        default:\n            return state\n    }\n}\n\nexport const reducer: Reducer<IExplorerState> = (\n    state: IExplorerState = DefaultExplorerState,\n    action: ExplorerAction,\n) => {\n    return {\n        ...state,\n        hasFocus: hasFocusReducer(state.hasFocus, action),\n        rootFolder: rootFolderReducer(state.rootFolder, action),\n        expandedFolders: expandedFolderReducer(state.expandedFolders, action),\n        fileToSelect: selectFileReducer(state.fileToSelect, action),\n        register: yankRegisterReducer(state.register, action),\n    }\n}\n\nconst setRootDirectoryEpic: Epic<ExplorerAction, IExplorerState> = (action$, store) =>\n    action$.ofType(\"SET_ROOT_DIRECTORY\").map((action: ISetRootDirectoryAction) => {\n        if (!action.rootPath) {\n            return Actions.Null\n        }\n\n        return Actions.expandDirectory(action.rootPath)\n    })\n\nconst sortFilesAndFoldersFunc = (a: FolderOrFile, b: FolderOrFile) => {\n    if (a.type < b.type) {\n        return 1\n    } else if (a.type > b.type) {\n        return -1\n    } else {\n        if (a.fullPath < b.fullPath) {\n            return -1\n        } else {\n            return 1\n        }\n    }\n}\n\n// Send Notifications ==================================================\ninterface INotificationDetails {\n    title: string\n    details: string\n    level?: NotificationLevel\n}\n\nconst sendExplorerNotification = (\n    { title, details, level = \"success\" }: INotificationDetails,\n    notifications: Notifications,\n) => {\n    const notification = notifications.createItem()\n    notification.setContents(title, details)\n    notification.setLevel(level)\n    notification.setExpiration(5_000)\n    notification.show()\n}\n\ninterface MoveNotificationArgs {\n    type: string\n    name: string\n    destination: string\n    notifications: Notifications\n}\nconst moveNotification = ({ type, name, destination, notifications }: MoveNotificationArgs) =>\n    sendExplorerNotification(\n        {\n            title: `${capitalize(type)} Moved`,\n            details: `Successfully moved ${name} to ${destination}`,\n        },\n        notifications,\n    )\ninterface SendNotificationArgs {\n    name: string\n    type: string\n    notifications: Notifications\n}\nconst deletionNotification = ({ type, name, notifications }: SendNotificationArgs): void =>\n    sendExplorerNotification(\n        {\n            title: `${capitalize(type)} deleted`,\n            details: `${path.basename(name)} was deleted successfully`,\n        },\n        notifications,\n    )\n\ninterface RenameNotificationArgs {\n    type: string\n    source: string\n    destination: string\n    notifications: Notifications\n}\n\nconst renameNotification = ({\n    notifications,\n    type,\n    source,\n    destination,\n}: RenameNotificationArgs): void =>\n    sendExplorerNotification(\n        {\n            title: `${capitalize(type)} renamed successfully`,\n            details: `${path.basename(source)} renamed to ${path.basename(destination)}`,\n        },\n        notifications,\n    )\n\ninterface CreationNotificationArgs {\n    notifications: Notifications\n    type: \"file\" | \"folder\"\n    name: string\n}\n\nconst creationNotification = ({ notifications, type, name }: CreationNotificationArgs): void =>\n    sendExplorerNotification(\n        {\n            title: `${capitalize(type)} created successfully`,\n            details: `${name} created`,\n        },\n        notifications,\n    )\n\ninterface ErrorNotificationArgs {\n    type: string\n    reason: string\n    notifications: Notifications\n}\n\nconst errorNotification = ({ type, reason, notifications }: ErrorNotificationArgs): void =>\n    sendExplorerNotification(\n        {\n            title: `${capitalize(type)} Failed`,\n            details: reason,\n            level: \"warn\",\n        },\n        notifications,\n    )\n\ninterface Dependencies {\n    fileSystem: IFileSystem\n    notifications: Notifications\n}\n\n// EPICS =============================================================\ntype ExplorerEpic = Epic<ExplorerAction, IExplorerState, Dependencies>\n\nexport const pasteEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"PASTE\").mergeMap(({ target, pasted }: IPasteAction) => {\n        const ids = pasted.map(item => item.id)\n        const clearRegister = Actions.clearRegister(ids)\n\n        return forkJoin(\n            pasted.map(async yankedItem => {\n                const { source, destination } = getSourceAndDestPaths(yankedItem, target)\n                await fileSystem.move(source, destination)\n                return { node: yankedItem, destination }\n            }),\n        )\n            .flatMap(moved => {\n                return [\n                    clearRegister,\n                    ...shouldExpandDirectory([target]),\n                    Actions.refresh,\n                    Actions.pasteSuccess(moved),\n                ]\n            })\n            .catch(error => {\n                Log.warn(error)\n                return [clearRegister, Actions.pasteFail(error.message)]\n            })\n    })\n\nconst successActions = (maybeDirsNodes: ExplorerNode[] = []) => [\n    Actions.undoSuccess,\n    ...shouldExpandDirectory(maybeDirsNodes),\n    Actions.refresh,\n]\n\nconst persistOrDeleteNode = async (\n    filepath: string,\n    fileSystem: IFileSystem,\n    persist = true,\n): Promise<void> => {\n    const maxSize = configuration.getValue(\"explorer.maxUndoFileSizeInBytes\")\n    const persistEnabled = configuration.getValue(\"explorer.persistDeletedFiles\")\n    const canPersistNode = await fileSystem.canPersistNode(filepath, maxSize)\n    persistEnabled && persist && canPersistNode\n        ? await fileSystem.persistNode(filepath)\n        : await fileSystem.deleteNode(filepath)\n}\n\nexport const undoEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"UNDO\").mergeMap(action => {\n        const {\n            register: { undo },\n        } = store.getState()\n        const lastAction = last(undo)\n\n        switch (lastAction.type) {\n            case \"PASTE\":\n                const { pasted, target: dir, sources } = lastAction\n                const filesAndFolders = pasted.map(file => getSourceAndDestPaths(file, dir))\n                return fromPromise(fileSystem.moveNodesBack(filesAndFolders))\n                    .flatMap(() => successActions(sources))\n                    .catch(error => {\n                        Log.warn(error)\n                        return [Actions.undoFail(\"Sorry we can't undo the laste paste action\")]\n                    })\n\n            case \"DELETE_SUCCESS\":\n                const { target } = lastAction\n                return lastAction.persist\n                    ? fromPromise(fileSystem.restoreNode(getPathForNode(target)))\n                          .flatMap(() => successActions([target]))\n                          .catch(error => {\n                              Log.warn(error)\n                              return [Actions.undoFail(\"The last deletion cannot be undone, sorry\")]\n                          })\n                    : [Actions.undoFail(\"The last deletion cannot be undone, sorry\")]\n\n            case \"RENAME_SUCCESS\":\n                const { source, destination } = lastAction\n                return fromPromise(fileSystem.move(destination, source))\n                    .flatMap(() => successActions())\n                    .catch(error => {\n                        Log.warn(error)\n                        return [Actions.undoFail(\"The last rename could not be undone, sorry\")]\n                    })\n\n            case \"CREATE_NODE_SUCCESS\":\n                return fromPromise(persistOrDeleteNode(lastAction.name, fileSystem))\n                    .flatMap(() => successActions())\n                    .catch(error => {\n                        Log.warn(error)\n                        return [\n                            Actions.undoFail(\n                                \"The last file/folder creation could not be undone, sorry\",\n                            ),\n                        ]\n                    })\n            default:\n                return [Actions.undoFail(\"Sorry we can't undo the last action\")]\n        }\n    })\n\nexport const deleteEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"DELETE\").mergeMap((action: IDeleteAction) => {\n        const { target, persist } = action\n        const filepath = getPathForNode(target)\n\n        return fromPromise(persistOrDeleteNode(filepath, fileSystem, persist))\n            .flatMap(() => [Actions.deleteSuccess(target, persist), Actions.refresh])\n            .catch(error => {\n                Log.warn(error)\n                return [Actions.deleteFail(error.message)]\n            })\n    })\n\nexport const renameEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"RENAME_COMMIT\").mergeMap(({ newName, target }: IRenameCommitAction) => {\n        const source = getPathForNode(target)\n        const destination = path.join(path.dirname(source), newName)\n        return fromPromise(fileSystem.move(source, destination))\n            .flatMap(() => [\n                Actions.renameSuccess({ source, destination, targetType: target.type }),\n                Actions.refresh,\n            ])\n            .catch(error => {\n                Log.warn(error)\n                return [Actions.renameFail(error.message)]\n            })\n    })\n\nexport const clearYankRegisterEpic: ExplorerEpic = (action$, store) =>\n    action$.ofType(\"YANK\").mergeMap((action: IYankAction) => {\n        const oneMinute = 60_000\n        return timer(oneMinute).mapTo(Actions.clearRegister([action.target.id]))\n    })\n\nexport const clearUpdateEpic: ExplorerEpic = (action$, store) =>\n    action$\n        .ofType(\"PASTE_SUCCESS\", \"UNDO_SUCCESS\", \"DELETE_SUCCESS\")\n        .mergeMap(() => timer(2_000).mapTo(Actions.clearUpdate))\n\nconst refreshEpic: ExplorerEpic = (action$, store) =>\n    action$\n        .ofType(\"REFRESH\")\n        .auditTime(300)\n        .mergeMap(() => {\n            const state = store.getState()\n\n            return Object.keys(state.expandedFolders).map(p => {\n                return Actions.expandDirectory(p)\n            })\n        })\n\nconst expandDirectoryEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"EXPAND_DIRECTORY\").flatMap(async (action: ExplorerAction) => {\n        if (action.type !== \"EXPAND_DIRECTORY\") {\n            return Actions.Null\n        }\n\n        const pathToExpand = action.directoryPath\n\n        const filesAndFolders = await fileSystem.readdir(pathToExpand)\n\n        const sortedFilesAndFolders = filesAndFolders.sort(sortFilesAndFoldersFunc)\n\n        return Actions.expandDirectoryResult(pathToExpand, sortedFilesAndFolders)\n    })\n\nexport const selectFileEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"SELECT_FILE\").mergeMap(({ filePath }: ISelectFileAction) => {\n        const rootPath = store.getState().rootFolder.fullPath\n\n        // We need to resolve any symlinks, since the buffer and workspace path can otherwise\n        // appear to be unrelated (at least on OSX).\n        return fromPromise(\n            Promise.all([fileSystem.realpath(rootPath), fileSystem.realpath(filePath)]),\n        ).flatMap(([realRootPath, realFilePath]): ExplorerAction[] => {\n            const relPath = path.relative(realRootPath, realFilePath)\n            // Can only select files in the workspace.\n            if (relPath.startsWith(\"..\") || path.isAbsolute(relPath)) {\n                const failure: ISelectFileFailAction = {\n                    type: \"SELECT_FILE_FAIL\",\n                    reason: `File is not in workspace: ${filePath}`,\n                }\n                return [failure]\n            }\n            // Get the list of directories to expand in the Explorer.\n            const relDirectoryPath = path.relative(realRootPath, path.dirname(realFilePath))\n            const directories = relDirectoryPath.split(path.sep)\n            const actions = []\n            // Expand each directory in turn from the project root down to the file we want.\n            for (let dirNum = 1; dirNum <= directories.length; dirNum++) {\n                const relParentDirectoryPath = directories.slice(0, dirNum).join(path.sep)\n                const parentDirectoryPath = path.join(rootPath, relParentDirectoryPath)\n                actions.push(Actions.expandDirectory(parentDirectoryPath))\n            }\n            // Update the state with the file path we want the VimNaviator to select.\n            const pending: ISelectFilePendingAction = {\n                type: \"SELECT_FILE_PENDING\",\n                filePath: realFilePath,\n            }\n            actions.push(pending)\n            return actions\n        })\n    })\n\nexport const createNodeEpic: ExplorerEpic = (action$, store, { fileSystem }) =>\n    action$.ofType(\"CREATE_NODE_COMMIT\").mergeMap(({ name }: ICreateNodeCommitAction) => {\n        const {\n            register: {\n                create: { nodeType },\n            },\n        } = store.getState()\n        const createFileOrFolder =\n            nodeType === \"file\" ? fileSystem.writeFile(name) : fileSystem.mkdir(name)\n        return fromPromise(createFileOrFolder)\n            .flatMap(() => [Actions.createNode({ nodeType, name }), Actions.selectFile(name)])\n            .catch(error => [Actions.createNodeFail(error.message)])\n    })\n\nexport const notificationEpic: ExplorerEpic = (action$, store, { notifications }) =>\n    action$\n        .ofType(\n            \"PASTE_SUCCESS\",\n            \"DELETE_SUCCESS\",\n            \"RENAME_SUCCESS\",\n            \"CREATE_NODE_SUCCESS\",\n            \"RENAME_FAIL\",\n            \"PASTE_FAIL\",\n            \"DELETE_FAIL\",\n            \"CREATE_NODE_FAIL\",\n            \"SELECT_FILE_FAIL\",\n        )\n        .map(action => {\n            switch (action.type) {\n                case \"PASTE_SUCCESS\":\n                    action.moved.map(item =>\n                        moveNotification({\n                            notifications,\n                            type: item.node.type,\n                            name: item.node.name,\n                            destination: item.destination,\n                        }),\n                    )\n                    return Actions.notificationSent(action.type)\n                case \"DELETE_SUCCESS\":\n                    deletionNotification({\n                        notifications,\n                        type: action.target.type,\n                        name: action.target.name,\n                    })\n                    return Actions.notificationSent(action.type)\n                case \"RENAME_SUCCESS\":\n                    renameNotification({\n                        notifications,\n                        type: action.targetType,\n                        source: action.source,\n                        destination: action.destination,\n                    })\n                    return Actions.notificationSent(action.type)\n                case \"CREATE_NODE_SUCCESS\":\n                    creationNotification({\n                        notifications,\n                        type: action.nodeType,\n                        name: action.name,\n                    })\n                    return Actions.notificationSent(action.type)\n                case \"PASTE_FAIL\":\n                case \"DELETE_FAIL\":\n                case \"RENAME_FAIL\":\n                case \"CREATE_NODE_FAIL\":\n                case \"SELECT_FILE_FAIL\":\n                    const [type] = action.type.split(\"_\")\n                    errorNotification({\n                        type,\n                        notifications,\n                        reason: action.reason,\n                    })\n                    return Actions.notificationSent(action.type)\n                default:\n                    return Actions.Null\n            }\n        })\n\ninterface ICreateStore {\n    fileSystem?: IFileSystem\n    notifications: Notifications\n}\n\nexport const createStore = ({\n    fileSystem = OniFileSystem,\n    notifications,\n}: ICreateStore): Store<IExplorerState> => {\n    return createReduxStore(\"Explorer\", reducer, DefaultExplorerState, [\n        createEpicMiddleware<ExplorerAction, IExplorerState, Dependencies>(\n            combineEpics(\n                refreshEpic,\n                setRootDirectoryEpic,\n                createNodeEpic,\n                clearUpdateEpic,\n                clearYankRegisterEpic,\n                renameEpic,\n                pasteEpic,\n                undoEpic,\n                deleteEpic,\n                expandDirectoryEpic,\n                selectFileEpic,\n                notificationEpic,\n            ),\n            { dependencies: { fileSystem, notifications } },\n        ),\n    ])\n}\n"
  },
  {
    "path": "browser/src/Services/Explorer/ExplorerView.tsx",
    "content": "/**\n * ExplorerSplit.tsx\n *\n */\n\nimport * as React from \"react\"\nimport * as DND from \"react-dnd\"\nimport HTML5Backend from \"react-dnd-html5-backend\"\nimport { connect } from \"react-redux\"\nimport { AutoSizer, CellMeasurer, CellMeasurerCache, List } from \"react-virtualized\"\nimport { compose } from \"redux\"\n\nimport { CSSTransition, TransitionGroup } from \"react-transition-group\"\n\nimport { css, enableMouse, styled } from \"./../../UI/components/common\"\nimport { TextInputView } from \"./../../UI/components/LightweightText\"\nimport { SidebarEmptyPaneView } from \"./../../UI/components/SidebarEmptyPaneView\"\nimport { SidebarContainerView, SidebarItemView } from \"./../../UI/components/SidebarItemView\"\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\nimport { VimNavigator } from \"./../../UI/components/VimNavigator\"\nimport { DragAndDrop, Droppeable } from \"./../DragAndDrop\"\n\nimport { commandManager } from \"./../CommandManager\"\nimport { FileIcon } from \"./../FileIcon\"\n\nimport * as ExplorerSelectors from \"./ExplorerSelectors\"\nimport { getPathForNode, IExplorerState } from \"./ExplorerStore\"\n\ntype Node = ExplorerSelectors.ExplorerNode\n\nexport interface INodeViewProps {\n    moveFileOrFolder: (source: Node, dest: Node) => void\n    node: ExplorerSelectors.ExplorerNode\n    isSelected: boolean\n    onClick: () => void\n    onCancelRename: () => void\n    onCompleteRename: (newName: string) => void\n    onCancelCreate?: () => void\n    onCompleteCreate?: (path: string) => void\n    yanked: string[]\n    updated?: string[]\n    isRenaming: Node\n    isCreating: boolean\n    children?: React.ReactNode\n}\n\nconst stopPropagation = (fn: () => void) => {\n    return (e?: React.MouseEvent<HTMLElement>) => {\n        if (e) {\n            e.stopPropagation()\n        }\n        fn()\n    }\n}\n\nconst Types = {\n    FILE: \"FILE\",\n    FOLDER: \"FOLDER\",\n}\n\ninterface IMoveNode {\n    drop: {\n        node: ExplorerSelectors.ExplorerNode\n    }\n    drag: {\n        node: ExplorerSelectors.ExplorerNode\n    }\n}\n\nexport const NodeWrapper = styled.div`\n    cursor: pointer;\n    &:hover {\n        text-decoration: underline;\n    }\n`\n\nconst NodeTransitionWrapper = styled.div`\n    transition: all 400ms 50ms ease-in-out;\n\n    &.move-enter {\n        opacity: 0.01;\n        transform: scale(0.9);\n    }\n\n    &.move-enter-active {\n        transform: scale(1);\n        opacity: 1;\n    }\n`\n\ninterface ITransitionProps {\n    children: React.ReactNode\n    updated: boolean\n}\n\nconst renameStyles = css`\n    width: 100%;\n    background-color: inherit;\n    color: inherit;\n    font-size: inherit;\n    font-family: inherit;\n    padding: 0.5em;\n    box-sizing: border-box;\n    border: 2px solid ${p => p.theme[\"highlight.mode.normal.background\"]} !important;\n`\n\nconst createStyles = css`\n    ${renameStyles};\n    margin-top: 0.2em;\n`\n\nconst Transition = ({ children, updated }: ITransitionProps) => (\n    <CSSTransition in={updated} classNames=\"move\" timeout={1000}>\n        <NodeTransitionWrapper className={updated && \"move\"}>{children}</NodeTransitionWrapper>\n    </CSSTransition>\n)\n\nexport class NodeView extends React.PureComponent<INodeViewProps> {\n    public moveFileOrFolder = ({ drag, drop }: IMoveNode) => {\n        this.props.moveFileOrFolder(drag.node, drop.node)\n    }\n\n    public isSameNode = ({ drag, drop }: IMoveNode) => {\n        return !(drag.node.name === drop.node.name)\n    }\n\n    public render() {\n        const { isCreating, isRenaming, isSelected, node } = this.props\n        const renameInProgress = isRenaming.name === node.name && isSelected && !isCreating\n        const creationInProgress = isCreating && isSelected && !renameInProgress\n        return (\n            <NodeWrapper>\n                {renameInProgress ? (\n                    <TextInputView\n                        styles={renameStyles}\n                        onCancel={this.props.onCancelRename}\n                        onComplete={this.props.onCompleteRename}\n                    />\n                ) : (\n                    <div>\n                        {this.getElement()}\n                        {creationInProgress && (\n                            <TextInputView\n                                styles={createStyles}\n                                onCancel={this.props.onCancelCreate}\n                                onComplete={this.props.onCompleteCreate}\n                            />\n                        )}\n                    </div>\n                )}\n            </NodeWrapper>\n        )\n    }\n\n    public hasUpdated = (path: string) =>\n        !!this.props.updated && this.props.updated.some(nodePath => nodePath === path)\n\n    public getElement() {\n        const { node } = this.props\n        const yanked = this.props.yanked.includes(node.id)\n\n        switch (node.type) {\n            case \"file\":\n                return (\n                    <DragAndDrop\n                        onDrop={this.moveFileOrFolder}\n                        dragTarget={Types.FILE}\n                        accepts={[Types.FILE, Types.FOLDER]}\n                        isValidDrop={this.isSameNode}\n                        node={node}\n                        render={({ canDrop, isDragging, didDrop, isOver }) => {\n                            const updated = this.hasUpdated(node.filePath)\n                            return (\n                                <Transition updated={updated}>\n                                    <SidebarItemView\n                                        updated={updated}\n                                        yanked={yanked}\n                                        isOver={isOver && canDrop}\n                                        didDrop={didDrop}\n                                        canDrop={canDrop}\n                                        text={node.name}\n                                        isFocused={this.props.isSelected}\n                                        isContainer={false}\n                                        indentationLevel={node.indentationLevel}\n                                        onClick={stopPropagation(this.props.onClick)}\n                                        icon={<FileIcon fileName={node.name} isLarge={true} />}\n                                    />\n                                </Transition>\n                            )\n                        }}\n                    />\n                )\n            case \"container\":\n                return (\n                    <Droppeable\n                        accepts={[Types.FILE, Types.FOLDER]}\n                        onDrop={this.moveFileOrFolder}\n                        isValidDrop={() => true}\n                        render={({ isOver }) => {\n                            return (\n                                <SidebarContainerView\n                                    yanked={yanked}\n                                    isOver={isOver}\n                                    isContainer={true}\n                                    isExpanded={node.expanded}\n                                    text={node.name}\n                                    isFocused={this.props.isSelected}\n                                    onClick={stopPropagation(this.props.onClick)}\n                                />\n                            )\n                        }}\n                    />\n                )\n            case \"folder\":\n                return (\n                    <DragAndDrop\n                        accepts={[Types.FILE, Types.FOLDER]}\n                        dragTarget={Types.FOLDER}\n                        isValidDrop={this.isSameNode}\n                        onDrop={this.moveFileOrFolder}\n                        node={node}\n                        render={({ isOver, didDrop, canDrop }) => {\n                            const updated = this.hasUpdated(node.folderPath)\n                            return (\n                                <Transition updated={updated}>\n                                    <SidebarContainerView\n                                        yanked={yanked}\n                                        updated={updated}\n                                        didDrop={didDrop}\n                                        isOver={isOver && canDrop}\n                                        isContainer={false}\n                                        isExpanded={node.expanded}\n                                        text={node.name}\n                                        isFocused={this.props.isSelected}\n                                        indentationLevel={node.indentationLevel}\n                                        onClick={stopPropagation(this.props.onClick)}\n                                    />\n                                </Transition>\n                            )\n                        }}\n                    />\n                )\n            default:\n                return <div>{JSON.stringify(node)}</div>\n        }\n    }\n}\n\nexport interface IExplorerViewContainerProps {\n    moveFileOrFolder: (source: Node, dest: Node) => void\n    onSelectionChanged: (id: string) => void\n    onClick: (id: string) => void\n    onCancelRename: () => void\n    onCompleteRename: (newName: string) => void\n    yanked?: string[]\n    isCreating?: boolean\n    isRenaming?: Node\n    onCancelCreate?: () => void\n    onCompleteCreate?: (path: string) => void\n}\n\nexport interface IExplorerViewProps extends IExplorerViewContainerProps {\n    nodes: ExplorerSelectors.ExplorerNode[]\n    isActive: boolean\n    updated: string[]\n    idToSelect: string\n}\n\ninterface ISneakableNode extends IExplorerViewProps {\n    node: Node\n    selectedId: string\n}\n\nconst SneakableNode = ({ node, selectedId, ...props }: ISneakableNode) => (\n    <Sneakable callback={() => props.onClick(node.id)}>\n        <NodeView\n            node={node}\n            isSelected={node.id === selectedId}\n            isCreating={props.isCreating}\n            onCancelCreate={props.onCancelCreate}\n            onCompleteCreate={props.onCompleteCreate}\n            onCompleteRename={props.onCompleteRename}\n            isRenaming={props.isRenaming}\n            onCancelRename={props.onCancelRename}\n            updated={props.updated}\n            yanked={props.yanked}\n            moveFileOrFolder={props.moveFileOrFolder}\n            onClick={() => props.onClick(node.id)}\n        />\n    </Sneakable>\n)\n\nconst ExplorerContainer = styled.div`\n    height: 100%;\n    ${enableMouse};\n`\n\nexport class ExplorerView extends React.PureComponent<IExplorerViewProps> {\n    private _list = React.createRef<List>()\n\n    private _cache = new CellMeasurerCache({\n        defaultHeight: 30,\n        fixedWidth: true,\n    })\n\n    public openWorkspaceFolder = () => {\n        commandManager.executeCommand(\"workspace.openFolder\")\n    }\n\n    public getSelectedNode = (selectedId: string) => {\n        return this.props.nodes.findIndex(n => selectedId === n.id)\n    }\n\n    public propsChanged(keys: Array<keyof IExplorerViewProps>, prevProps: IExplorerViewProps) {\n        return keys.some(prop => this.props[prop] !== prevProps[prop])\n    }\n\n    public componentDidUpdate(prevProps: IExplorerViewProps) {\n        if (this.propsChanged([\"isCreating\", \"isRenaming\", \"yanked\"], prevProps)) {\n            // TODO: if we could determine which nodes actually were involved\n            // in the change this could potentially be optimised\n            this._cache.clearAll()\n            this._list.current.recomputeRowHeights()\n        }\n    }\n\n    public render() {\n        const ids = this.props.nodes.map(node => node.id)\n        const isActive = this.props.isActive && !this.props.isRenaming && !this.props.isCreating\n\n        if (!this.props.nodes || !this.props.nodes.length) {\n            return (\n                <SidebarEmptyPaneView\n                    active={this.props.isActive}\n                    contentsText=\"Nothing to show here, yet!\"\n                    actionButtonText=\"Open a Folder\"\n                    onClickButton={this.openWorkspaceFolder}\n                />\n            )\n        }\n\n        return (\n            <TransitionGroup style={{ height: \"100%\" }}>\n                <VimNavigator\n                    ids={ids}\n                    active={isActive}\n                    style={{ height: \"100%\" }}\n                    idToSelect={this.props.idToSelect}\n                    onSelected={id => this.props.onClick(id)}\n                    onSelectionChanged={this.props.onSelectionChanged}\n                    render={selectedId => {\n                        return (\n                            <ExplorerContainer className=\"explorer\">\n                                <AutoSizer>\n                                    {measurements => (\n                                        <List\n                                            {...measurements}\n                                            ref={this._list}\n                                            scrollToAlignment=\"end\"\n                                            style={{ outline: \"none\" }}\n                                            rowCount={this.props.nodes.length}\n                                            rowHeight={this._cache.rowHeight}\n                                            scrollToIndex={this.getSelectedNode(selectedId)}\n                                            rowRenderer={({ index, style, key, parent }) => (\n                                                <CellMeasurer\n                                                    key={key}\n                                                    cache={this._cache}\n                                                    columnIndex={0}\n                                                    parent={parent}\n                                                    rowIndex={index}\n                                                >\n                                                    <div\n                                                        style={style}\n                                                        key={this.props.nodes[index].id}\n                                                    >\n                                                        <SneakableNode\n                                                            {...this.props}\n                                                            selectedId={selectedId}\n                                                            node={this.props.nodes[index]}\n                                                        />\n                                                    </div>\n                                                </CellMeasurer>\n                                            )}\n                                        />\n                                    )}\n                                </AutoSizer>\n                            </ExplorerContainer>\n                        )\n                    }}\n                />\n            </TransitionGroup>\n        )\n    }\n}\n\nconst getIdToSelect = (fileToSelect: string, nodes: ExplorerSelectors.ExplorerNode[]) => {\n    // If parent has told us to select a file, attempt to convert the file path into a node ID.\n    if (fileToSelect) {\n        const [nodeToSelect] = nodes.filter(node => {\n            const nodePath = getPathForNode(node)\n            return nodePath === fileToSelect\n        })\n\n        return nodeToSelect ? nodeToSelect.id : null\n    }\n    return null\n}\n\nconst mapStateToProps = (\n    state: IExplorerState,\n    containerProps: IExplorerViewContainerProps,\n): IExplorerViewProps => {\n    const yanked = state.register.yank.map(node => node.id)\n    const {\n        register: { updated, rename },\n        fileToSelect,\n    } = state\n\n    const nodes: ExplorerSelectors.ExplorerNode[] = ExplorerSelectors.mapStateToNodeList(state)\n\n    return {\n        ...containerProps,\n        isActive: state.hasFocus,\n        nodes,\n        updated,\n        yanked,\n        idToSelect: getIdToSelect(fileToSelect, nodes),\n        isCreating: state.register.create.active,\n        isRenaming: rename.active && rename.target,\n    }\n}\n\nexport const Explorer = compose(connect(mapStateToProps), DND.DragDropContext(HTML5Backend))(\n    ExplorerView,\n)\n"
  },
  {
    "path": "browser/src/Services/Explorer/index.tsx",
    "content": "/**\n * Explorer/index.tsx\n *\n * Entry point for explorer-related features\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { CallbackCommand } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { SidebarManager } from \"./../Sidebar\"\n\nimport { ExplorerSplit } from \"./ExplorerSplit\"\n\nexport const activate = (\n    oni: Oni.Plugin.Api,\n    configuration: Configuration,\n    sidebarManager: SidebarManager,\n) => {\n    configuration.registerSetting(\"explorer.autoRefresh\", {\n        description:\n            \"When set to true, the explorer will listen for changes on the file system and refresh automatically.\",\n        requiresReload: true,\n        defaultValue: false,\n    })\n\n    const explorerSplit: ExplorerSplit = new ExplorerSplit(oni)\n    sidebarManager.add(\"files-o\", explorerSplit)\n\n    const explorerId = \"oni.sidebar.explorer\"\n\n    oni.commands.registerCommand(\n        new CallbackCommand(\n            \"explorer.toggle\",\n            \"Explorer: Toggle Visibility\",\n            \"Toggles the explorer in the sidebar\",\n            () => sidebarManager.toggleVisibilityById(explorerId),\n            () => !!oni.workspace.activeWorkspace,\n        ),\n    )\n\n    oni.commands.registerCommand(\n        new CallbackCommand(\n            \"explorer.locate.buffer\",\n            \"Explorer: Locate Current Buffer\",\n            \"Locate current buffer in file tree\",\n            () => {\n                if (sidebarManager.activeEntryId !== explorerId || !sidebarManager.isVisible) {\n                    sidebarManager.setActiveEntry(explorerId)\n                }\n                explorerSplit.locateFile(oni.editors.activeEditor.activeBuffer.filePath)\n            },\n            () => !!oni.workspace.activeWorkspace,\n        ),\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/FileIcon.tsx",
    "content": "/**\n * Icons\n *\n * - Data source for icons present in Oni\n * - Loads icons based on the `ui.iconTheme` configuration setting\n */\n\nimport * as React from \"react\"\n\nimport { css, keyframes, styled, withProps } from \"../UI/components/common\"\nimport { getInstance } from \"./IconThemes\"\n\nconst appearAnimationKeyframes = keyframes`\n    0% {\n        opacity: 0;\n        transform: scale(0.8);\n    }\n    100% {\n        opacity: 1;\n        transform: scale(1);\n    }\n`\n\nconst appearAnimation = css`\n    animation-name: ${appearAnimationKeyframes};\n    animation-duration: 0.25s;\n    animation-timing-function: ease-in;\n    animation-fill-mode: forwards;\n    opacity: 1;\n`\n\nconst Icon = withProps<{ playAppearAnimation: boolean }>(styled.i)`\n    ${props => (props.playAppearAnimation ? appearAnimation : \"\")}\n`\n\nexport interface IFileIconProps {\n    fileName: string\n    language?: string\n\n    isLarge?: boolean\n\n    playAppearAnimation?: boolean\n}\n\nexport const FileIcon = (props: IFileIconProps) => {\n    if (!props.fileName) {\n        return null\n    }\n\n    const icons = getInstance()\n\n    const className =\n        icons.getIconClassForFile(props.fileName, props.language) + (props.isLarge ? \" fa-lg\" : \"\")\n\n    return (\n        <Icon\n            playAppearAnimation={!!props.playAppearAnimation}\n            className={className}\n            aria-hidden={true}\n        />\n    )\n}\n\nexport const getFileIcon = (fileName: string) => <FileIcon fileName={fileName} isLarge={true} />\n"
  },
  {
    "path": "browser/src/Services/FileMappings.ts",
    "content": "/**\n * FileMappings.ts\n *\n * Shared code / utilities for mapping files\n */\n\nimport * as path from \"path\"\n\nexport interface IFileMapping {\n    sourceFolder: string\n    sourceFilesGlob?: string\n\n    mappedFolder: string\n    mappedFileName: string\n\n    templateFilePath?: string\n}\n\nexport interface IFileMappingResult {\n    fullPath: string\n    templateFileFullPath?: string\n}\n\nexport const getMappedFile = (\n    rootFolder: string,\n    filePath: string,\n    mappings: IFileMapping[],\n): IFileMappingResult | null => {\n    const mappingsThatApply = mappings.filter(m => doesMappingMatchFile(rootFolder, filePath, m))\n\n    if (mappingsThatApply.length === 0) {\n        return null\n    }\n\n    const mapping = mappingsThatApply[0]\n\n    const fullPath = getMappedFileFromMapping(rootFolder, filePath, mapping)\n    const templateFileFullPath = mapping.templateFilePath\n        ? path.join(rootFolder, mapping.templateFilePath)\n        : null\n\n    return {\n        fullPath,\n        templateFileFullPath,\n    }\n}\n\nexport const doesMappingMatchFile = (\n    rootFolder: string,\n    filePath: string,\n    mapping: IFileMapping,\n): boolean => {\n    return filePath.indexOf(path.join(rootFolder, mapping.sourceFolder)) === 0\n}\n\nexport const getMappedFileFromMapping = (\n    rootFolder: string,\n    filePath: string,\n    mapping: IFileMapping,\n): string | null => {\n    const fullSourceRoot = path.join(rootFolder, mapping.sourceFolder)\n    const difference = getPathDifference(fullSourceRoot, path.dirname(filePath))\n\n    // Resolve the variables in the file path, like `${fileName}`\n    const resolvedMappedFile = replaceVariablesInFileName(mapping.mappedFileName, filePath)\n\n    const mappedFile = path.join(rootFolder, mapping.mappedFolder, difference, resolvedMappedFile)\n    return mappedFile\n}\n\nexport const replaceVariablesInFileName = (\n    mappingFileNameWithVariables: string,\n    originalFilePath: string,\n): string => {\n    const originalFileNameWithExtension = path.basename(originalFilePath)\n    const originalExtension = path.extname(originalFileNameWithExtension)\n\n    const originalFileNameWithoutExtension = path.basename(originalFilePath, originalExtension)\n\n    let ret = mappingFileNameWithVariables\n\n    // Resolve '${fileName}' variable\n    ret = ret.split(\"${fileName}\").join(originalFileNameWithoutExtension) // tslint:disable-line\n\n    return ret\n}\n\nexport const getPathDifference = (path1: string, path2: string): string => {\n    const path1Parts = splitPath(path1) || []\n    const path2Parts = splitPath(path2) || []\n\n    const deltaPathParts = []\n\n    const basePathParts = path1Parts.length < path2Parts.length ? path1Parts : path2Parts\n    const diffPathParts = path1Parts.length < path2Parts.length ? path2Parts : path1Parts\n\n    let idx = 0\n    let isEqual: boolean = true\n    while (idx < diffPathParts.length) {\n        if (idx >= basePathParts.length) {\n            deltaPathParts.push(diffPathParts[idx])\n        } else {\n            if (isEqual && basePathParts[idx] === diffPathParts[idx]) {\n                // just continue\n            } else {\n                isEqual = false\n                deltaPathParts.push(diffPathParts[idx])\n            }\n        }\n\n        idx++\n    }\n\n    return path.join.apply(path, deltaPathParts)\n}\n\nexport const splitPath = (fullPath: string): string[] => {\n    return path.normalize(fullPath).split(path.sep)\n}\n"
  },
  {
    "path": "browser/src/Services/FileSystemWatcher/index.ts",
    "content": "import * as chokidar from \"chokidar\"\nimport { Stats } from \"fs\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as Log from \"oni-core-logging\"\n\nexport type Targets = string | string[]\n\ninterface IFSOptions {\n    options?: chokidar.WatchOptions\n    target?: Targets\n}\n\ninterface IFileChangeEvent {\n    path: string\n}\n\ninterface IStatsChangeEvent {\n    path: string\n    stats: Stats\n}\n\nexport class FileSystemWatcher {\n    private _watcher: chokidar.FSWatcher\n\n    private _onAdd = new Event<IFileChangeEvent>()\n    private _onAddDir = new Event<IStatsChangeEvent>()\n    private _onDelete = new Event<IFileChangeEvent>()\n    private _onDeleteDir = new Event<IFileChangeEvent>()\n    private _onMove = new Event<IFileChangeEvent>()\n    private _onChange = new Event<IFileChangeEvent>()\n\n    constructor({ target, options }: IFSOptions) {\n        this._watcher = chokidar.watch(target, options)\n\n        this._watcher.on(\"ready\", () => {\n            this._attachEventListeners()\n        })\n\n        this._watcher.on(\"error\", err => {\n            Log.warn(\"FileSystemWatcher encountered an error: \" + err)\n        })\n    }\n\n    public watch(target: Targets) {\n        return this._watcher.add(target)\n    }\n\n    public unwatch(target: Targets) {\n        return this._watcher.unwatch(target)\n    }\n\n    public close() {\n        this._watcher.close()\n    }\n\n    private _attachEventListeners() {\n        this._watcher.on(\"add\", path => {\n            return this._onAdd.dispatch(path)\n        })\n\n        this._watcher.on(\"change\", path => {\n            return this._onChange.dispatch(path)\n        })\n\n        this._watcher.on(\"move\", path => {\n            return this._onMove.dispatch(path)\n        })\n\n        this._watcher.on(\"unlink\", path => {\n            return this._onDelete.dispatch(path)\n        })\n\n        this._watcher.on(\"unlinkDir\", path => {\n            return this._onDeleteDir.dispatch(path)\n        })\n\n        this._watcher.on(\"addDir\", (path, stats) => {\n            return this._onAddDir.dispatch({ path, stats })\n        })\n    }\n\n    get allWatched(): chokidar.WatchedPaths {\n        return this._watcher.getWatched()\n    }\n\n    get onChange(): IEvent<IFileChangeEvent> {\n        return this._onChange\n    }\n\n    get onDelete(): IEvent<IFileChangeEvent> {\n        return this._onDelete\n    }\n\n    get onDeleteDir(): IEvent<IFileChangeEvent> {\n        return this._onDeleteDir\n    }\n\n    get onMove(): IEvent<IFileChangeEvent> {\n        return this._onMove\n    }\n\n    get onAdd(): IEvent<IFileChangeEvent> {\n        return this._onAdd\n    }\n\n    get onAddDir(): IEvent<IFileChangeEvent> {\n        return this._onAddDir\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/FocusManager.ts",
    "content": "/*\n * FocusManager.ts\n */\n\nimport * as Log from \"oni-core-logging\"\n\nclass FocusManager {\n    private _focusElementStack: HTMLElement[] = []\n\n    public get focusedElement(): HTMLElement | null {\n        return this._focusElementStack.length > 0 ? this._focusElementStack[0] : null\n    }\n\n    public pushFocus(element: HTMLElement) {\n        this._focusElementStack = [element, ...this._focusElementStack]\n\n        window.setTimeout(() => this.enforceFocus(), 0)\n    }\n\n    public popFocus(element: HTMLElement) {\n        this._focusElementStack = this._focusElementStack.filter(elem => elem !== element)\n\n        this.enforceFocus()\n    }\n\n    public setFocus(element: HTMLElement): void {\n        if (element) {\n            this._focusElementStack = [element]\n            element.focus()\n        } else {\n            Log.warn(\"FocusManager.setFocus called with null element\")\n        }\n    }\n\n    public enforceFocus(): void {\n        if (this._focusElementStack.length === 0) {\n            return\n        }\n\n        const activeElement = this._focusElementStack[0]\n        if (activeElement !== document.activeElement) {\n            activeElement.focus()\n        }\n    }\n}\n\nexport const focusManager = new FocusManager()\n"
  },
  {
    "path": "browser/src/Services/IconThemes/IconThemeLoader.ts",
    "content": "/**\n * IconThemeLoader.ts\n *\n * Class responsible for loading an icon theme\n */\n\nimport * as fs from \"fs\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { IIconThemeContribution } from \"./../../Plugins/Api/Capabilities\"\n\nimport { IIconTheme } from \"./Icons\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nexport interface IIconThemeLoadResult {\n    theme: IIconTheme\n    filePath: string\n}\n\nexport interface IIconThemeLoader {\n    loadIconTheme(themeName: string): Promise<IIconThemeLoadResult>\n}\n\nexport class PluginIconThemeLoader {\n    constructor(private _pluginManager: PluginManager) {}\n\n    public async loadIconTheme(themeName: string): Promise<IIconThemeLoadResult> {\n        const plugins = this._pluginManager.plugins\n\n        const pluginsWithThemes = plugins.filter(p => {\n            return p.metadata && p.metadata.contributes && p.metadata.contributes.iconThemes\n        })\n\n        const allIconThemes = pluginsWithThemes.reduce(\n            (previous: IIconThemeContribution[], current) => {\n                const iconThemes = current.metadata.contributes.iconThemes\n                return [...previous, ...iconThemes]\n            },\n            [] as IIconThemeContribution[],\n        )\n\n        const matchingIconTheme = allIconThemes.find(t => t.id === themeName)\n\n        if (!matchingIconTheme || !matchingIconTheme.path) {\n            return null\n        }\n\n        const contents = await new Promise<string>((resolve, reject) => {\n            fs.readFile(matchingIconTheme.path, \"utf8\", (err, data: string) => {\n                if (err) {\n                    reject(err)\n                    return\n                }\n\n                resolve(data)\n            })\n        })\n\n        let theme = null\n        try {\n            theme = JSON.parse(contents) as IIconTheme\n        } catch (ex) {\n            Log.error(\"Error loading icon theme: \" + ex)\n        }\n\n        return {\n            theme,\n            filePath: matchingIconTheme.path,\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/IconThemes/Icons.ts",
    "content": "/**\n * Icons\n *\n * - Data source for icons present in Oni\n * - Loads icons based on the `ui.iconTheme` configuration setting\n */\n\nimport * as path from \"path\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { PluginIconThemeLoader } from \"./IconThemeLoader\"\nimport { StyleWriter } from \"./StyleWriter\"\n\nimport * as Utility from \"./../../Utility\"\n\nexport interface IIconFontSource {\n    path: string\n    format: string\n}\n\nexport interface IIconFont {\n    id: string\n    src: IIconFontSource[]\n    weight: string\n    style: string\n    size: string\n}\n\nexport interface IIconDefinition {\n    fontCharacter: string\n    fontColor: string\n}\n\nexport interface IIconInfo extends IIconDefinition {\n    fontFamily: string\n    weight: string\n    style: string\n    size: string\n}\n\nexport interface IconDefinitions {\n    [key: string]: IIconDefinition\n}\n\n// File extension -> icon definition key\nexport interface FileDefinitions {\n    [extension: string]: string\n}\n\n// File name -> icon definition key\nexport interface FileNames {\n    [fileName: string]: string\n}\n\n// Language id -> icon definition key\nexport interface Language {\n    [language: string]: string\n}\n\nexport interface IIconTheme {\n    fonts: IIconFont[]\n    iconDefinitions: IconDefinitions\n    file: string\n    fileExtensions: FileDefinitions\n    fileNames: FileNames\n    languageIds: Language\n    light?: IIconTheme\n}\n\nexport class Icons {\n    private _activeIconTheme: IIconTheme = null\n    private _onIconThemeChangedEvent: Event<void> = new Event<void>()\n\n    public get activeIconTheme(): IIconTheme {\n        return this._activeIconTheme\n    }\n\n    public get onIconThemeChanged(): IEvent<void> {\n        return this._onIconThemeChangedEvent\n    }\n\n    constructor(private _pluginManager: PluginManager) {}\n\n    public getIconClassForFile(fileName: string, language?: string): string {\n        if (!this._activeIconTheme) {\n            return null\n        }\n\n        const normalizedFileName = fileName.toLowerCase()\n        const classBase = \"fa oni-icon oni-icon-\"\n\n        // First, see if there is a matching file name\n        if (this._activeIconTheme.fileNames) {\n            const fileNameIcon = this._activeIconTheme.fileNames[normalizedFileName]\n\n            if (fileNameIcon) {\n                return classBase + fileNameIcon\n            }\n        }\n\n        // Next, see if there is a matching extension\n        if (this._activeIconTheme.fileExtensions) {\n            const extension = path.extname(fileName)\n            if (extension && extension.length > 1) {\n                const extensionWithoutPeriod = extension.substring(1, extension.length)\n\n                const matchingExtension = this._activeIconTheme.fileExtensions[\n                    extensionWithoutPeriod\n                ]\n                if (matchingExtension) {\n                    return classBase + matchingExtension\n                }\n            }\n        }\n\n        // Finally, see if there is a matching language\n        if (language && this._activeIconTheme.languageIds) {\n            const matchingLanguage = this._activeIconTheme.languageIds[language]\n\n            if (matchingLanguage) {\n                return classBase + matchingLanguage\n            }\n        }\n\n        if (this._activeIconTheme.file) {\n            return classBase + this._activeIconTheme.file\n        }\n\n        return null\n    }\n\n    public async applyIconTheme(themeName: string): Promise<void> {\n        const iconThemeLoader = new PluginIconThemeLoader(this._pluginManager)\n\n        const loadResults = await iconThemeLoader.loadIconTheme(themeName)\n\n        if (!loadResults || !loadResults.theme) {\n            return\n        }\n\n        this._activeIconTheme = loadResults.theme\n\n        const newStyle = document.createElement(\"style\")\n        const styleWriter = new StyleWriter(\"oni-icon\")\n\n        const fonts = this._activeIconTheme.fonts || []\n\n        fonts.forEach(font => {\n            if (!font.src || !font.src.length) {\n                return\n            }\n\n            const fontSrc = font.src[0]\n            const fontPath = Utility.normalizePath(\n                path.join(path.dirname(loadResults.filePath), fontSrc.path),\n            )\n            const fontFormat = fontSrc.format\n\n            styleWriter.writeFontFace(font.id, fontPath, fontFormat)\n        })\n\n        const iconDefinitions = this._activeIconTheme.iconDefinitions\n        if (iconDefinitions) {\n            Object.keys(iconDefinitions).forEach((definitionName: string) => {\n                const definitionContents = iconDefinitions[definitionName]\n                styleWriter.writeIcon(\n                    definitionName,\n                    definitionContents.fontColor,\n                    definitionContents.fontCharacter,\n                )\n            })\n        }\n\n        newStyle.appendChild(document.createTextNode(styleWriter.style))\n\n        document.head.appendChild(newStyle)\n\n        this._onIconThemeChangedEvent.dispatch()\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/IconThemes/StyleWriter.ts",
    "content": "/**\n * StyleWriter.ts\n *\n * Helper to generate text for an inline style element\n */\n\nimport * as os from \"os\"\n\nexport class StyleWriter {\n    private _style: string = \"\"\n\n    public get style(): string {\n        return this._style\n    }\n\n    constructor(private _primaryClassName: string) {}\n\n    public writeFontFace(fontFamily: string, sourceUrl: string, format: string): void {\n        // Inspired by:\n        // https://stackoverflow.com/questions/11355147/font-face-changing-via-javascript\n        const fontFaceBlock = [\n            \"@font-face {\",\n            `   font-family: ${fontFamily};`,\n            `   src: url('${sourceUrl}') format('${format}');`,\n            \"}\",\n        ]\n\n        this._append(fontFaceBlock)\n\n        const primaryClassBlock = [\n            \".fa.\" + this._primaryClassName + \" {\",\n            \"font-family: \" + fontFamily + \";\",\n            \"}\",\n        ]\n\n        this._append(primaryClassBlock)\n    }\n\n    public writeIcon(iconName: string, fontColor: string, fontCharacter: string): void {\n        const iconClass = this._primaryClassName + \"-\" + iconName\n        const selector = \".fa.\" + this._primaryClassName + \".\" + iconClass\n\n        if (fontColor) {\n            const primaryClassBlock = [selector + \" {\", \"color: \" + fontColor + \";\", \"}\"]\n            this._append(primaryClassBlock)\n        }\n\n        const pseudoElementBlock = [selector + \":before {\", `   content: '${fontCharacter}';`, \"}\"]\n        this._append(pseudoElementBlock)\n    }\n\n    private _append(str: string[]): void {\n        this._style += str.join(os.EOL) + os.EOL\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/IconThemes/index.ts",
    "content": "/**\n * Icons\n *\n * - Data source for icons present in Oni\n * - Loads icons based on the `ui.iconTheme` configuration setting\n */\nexport * from \"./Icons\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { Configuration } from \"./../Configuration\"\n\nimport { Icons } from \"./Icons\"\n\nlet _icons: Icons = null\n\nexport const getInstance = (): Icons => {\n    return _icons\n}\n\nexport const activate = async (\n    configuration: Configuration,\n    pluginManager: PluginManager,\n): Promise<void> => {\n    _icons = new Icons(pluginManager)\n\n    const iconTheme = configuration.getValue(\"ui.iconTheme\")\n    await _icons.applyIconTheme(iconTheme)\n}\n"
  },
  {
    "path": "browser/src/Services/InputManager.ts",
    "content": "import * as Oni from \"oni-api\"\n\nimport { commandManager } from \"./CommandManager\"\n\nexport type ActionFunction = () => boolean\n\nexport type ActionOrCommand = string | ActionFunction\n\nexport type FilterFunction = () => boolean\n\nexport interface KeyBinding {\n    action: ActionOrCommand\n    filter?: FilterFunction\n}\n\nexport interface KeyBindingMap {\n    [key: string]: KeyBinding[]\n}\n\nconst MAX_DELAY_BETWEEN_KEY_CHORD = 250 /* milliseconds */\nconst MAX_CHORD_SIZE = 6\n\nimport { KeyboardResolver } from \"./../Input/Keyboard/KeyboardResolver\"\n\nimport {\n    getMetaKeyResolver,\n    ignoreMetaKeyResolver,\n    remapResolver,\n} from \"./../Input/Keyboard/Resolvers\"\n\nexport interface KeyPressInfo {\n    keyChord: string\n    time: number\n}\n\n// Helper method to filter a set of key presses such that they are only the potential chords\nexport const getRecentKeyPresses = (\n    keys: KeyPressInfo[],\n    maxTimeBetweenKeyPresses: number,\n): KeyPressInfo[] => {\n    const chords = keys.reduce(\n        (prev, curr) => {\n            if (prev.length === 0) {\n                return [curr]\n            }\n\n            const lastItem = prev[prev.length - 1]\n\n            if (curr.time - lastItem.time > maxTimeBetweenKeyPresses) {\n                return [curr]\n            } else {\n                return [...prev, curr]\n            }\n        },\n        [] as KeyPressInfo[],\n    )\n\n    return chords.slice(0, MAX_CHORD_SIZE)\n}\n\nexport class InputManager implements Oni.Input.InputManager {\n    private _boundKeys: KeyBindingMap = {}\n    private _resolver: KeyboardResolver\n    private _keys: KeyPressInfo[] = []\n\n    constructor() {\n        this._resolver = new KeyboardResolver()\n\n        this._resolver.addResolver(ignoreMetaKeyResolver)\n        this._resolver.addResolver(remapResolver)\n        this._resolver.addResolver(getMetaKeyResolver())\n    }\n\n    /**\n     * API Methods\n     */\n    public bind(\n        keyChord: string | string[],\n        action: ActionOrCommand,\n        filterFunction?: () => boolean,\n    ): Oni.DisposeFunction {\n        if (Array.isArray(keyChord)) {\n            const disposalFunctions = keyChord.map(key => this.bind(key, action, filterFunction))\n            return () => disposalFunctions.forEach(df => df())\n        }\n\n        const normalizedKeyChord = keyChord.toLowerCase()\n        const currentBinding = this._boundKeys[normalizedKeyChord] || []\n        const newBinding = { action, filter: filterFunction }\n\n        this._boundKeys[normalizedKeyChord] = [...currentBinding, newBinding]\n\n        return () => {\n            const existingBindings = this._boundKeys[normalizedKeyChord]\n\n            if (existingBindings) {\n                this._boundKeys[normalizedKeyChord] = existingBindings.filter(f => f !== newBinding)\n            }\n        }\n    }\n\n    public unbind(keyChord: string | string[]) {\n        if (Array.isArray(keyChord)) {\n            keyChord.forEach(key => this.unbind(key))\n            return\n        }\n\n        const normalizedKeyChord = keyChord.toLowerCase()\n        this._boundKeys[normalizedKeyChord] = []\n    }\n\n    public unbindAll() {\n        this._boundKeys = {}\n    }\n\n    /**\n     * Potential API methods\n     */\n    public hasBinding(keyChord: string): boolean {\n        return !!this._boundKeys[keyChord]\n    }\n\n    public get resolvers(): KeyboardResolver {\n        return this._resolver\n    }\n\n    // Returns an array of keys bound to a command\n    public getBoundKeys = (command: string): string[] => {\n        return Object.keys(this._boundKeys).reduce(\n            (prev: string[], currentValue: string) => {\n                const bindings = this._boundKeys[currentValue]\n                if (bindings.find(b => b.action === command)) {\n                    return [...prev, currentValue]\n                } else {\n                    return prev\n                }\n            },\n            [] as string[],\n        )\n    }\n\n    /**\n     * Internal Methods\n     */\n\n    // Triggers an action handler if there is a bound-key that passes the filter.\n    // Returns true if the key was handled and should not continue bubbling,\n    // false otherwise.\n    public handleKey(keyChord: string, time: number = new Date().getTime()): boolean {\n        if (keyChord === null) {\n            return false\n        }\n\n        const newKey: KeyPressInfo = {\n            keyChord,\n            time,\n        }\n\n        this._keys.push(newKey)\n        const potentialKeys = getRecentKeyPresses(this._keys, MAX_DELAY_BETWEEN_KEY_CHORD)\n        this._keys = [...potentialKeys]\n\n        // We'll try the longest key chord to the shortest\n        while (potentialKeys.length > 0) {\n            const fullChord = potentialKeys.map(k => k.keyChord).join(\"\")\n\n            if (this._handleKeyCore(fullChord)) {\n                this._keys = []\n                return true\n            }\n\n            potentialKeys.shift()\n        }\n\n        return false\n    }\n\n    private _handleKeyCore(keyChord: string): boolean {\n        if (!this._boundKeys[keyChord]) {\n            return false\n        }\n\n        const boundKey = this._boundKeys[keyChord]\n\n        // tslint:disable-next-line prefer-for-of\n        for (let i = 0; i < boundKey.length; i++) {\n            const binding = boundKey[i]\n\n            // Does the binding pass filter?\n            if (binding.filter && !binding.filter()) {\n                continue\n            }\n\n            const action = binding.action\n            if (typeof action === \"string\") {\n                const result = commandManager.executeCommand(action, null)\n\n                if (result !== false) {\n                    return true\n                }\n            } else {\n                const result = action()\n\n                if (result !== false) {\n                    return true\n                }\n            }\n        }\n\n        return false\n    }\n}\n\nexport const inputManager = new InputManager()\n"
  },
  {
    "path": "browser/src/Services/KeyDisplayer/KeyDisplayer.tsx",
    "content": "/**\n * KeyDisplayer\n *\n * Utility for showing keys while typing\n */\n\nimport * as React from \"react\"\nimport { Provider } from \"react-redux\"\nimport { Store } from \"redux\"\n\nimport { IDisposable } from \"oni-types\"\n\nimport { parseChordParts } from \"./../../Input/KeyParser\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { InputManager } from \"./../InputManager\"\nimport { Overlay, OverlayManager } from \"./../Overlay\"\n\nimport { createStore, KeyDisplayerState } from \"./KeyDisplayerStore\"\nimport { KeyDisplayerContainer } from \"./KeyDisplayerView\"\n\nexport class KeyDisplayer {\n    private _activeOverlay: Overlay = null\n    private _currentResolveSubscription: IDisposable = null\n    private _store: Store<KeyDisplayerState>\n\n    constructor(\n        private _configuration: Configuration,\n        private _editorManager: EditorManager,\n        private _inputManager: InputManager,\n        private _overlayManager: OverlayManager,\n    ) {\n        this._store = createStore()\n    }\n\n    public get isActive(): boolean {\n        return this._currentResolveSubscription !== null\n    }\n\n    public start(): void {\n        this._currentResolveSubscription = this._inputManager.resolvers.addResolver(\n            (evt, resolution) => {\n                if (this._activeOverlay) {\n                    this._activeOverlay.hide()\n                    this._activeOverlay = null\n                }\n\n                if (\n                    !this._configuration.getValue(\"keyDisplayer.showInInsertMode\") &&\n                    this._editorManager.activeEditor.mode === \"insert\"\n                ) {\n                    return resolution\n                }\n\n                this._store.dispatch({\n                    type: \"ADD_KEY\",\n                    key: parseChordParts(resolution).join(\"+\"),\n                    timeInMilliseconds: new Date().getTime(),\n                })\n\n                this._activeOverlay = this._overlayManager.createItem()\n                this._activeOverlay.setContents(\n                    <Provider store={this._store}>\n                        <KeyDisplayerContainer />\n                    </Provider>,\n                )\n                this._activeOverlay.show()\n                return resolution\n            },\n        )\n    }\n\n    public end(): void {\n        this._store.dispatch({ type: \"RESET\" })\n        if (this._currentResolveSubscription) {\n            this._currentResolveSubscription.dispose()\n            this._currentResolveSubscription = null\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/KeyDisplayer/KeyDisplayerStore.ts",
    "content": "/**\n * KeyDisplayerStore\n *\n * State management for the KeyDisplayer\n */\n\nimport { Reducer, Store } from \"redux\"\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nimport { createEpicMiddleware, Epic } from \"redux-observable\"\nimport \"rxjs/add/operator/delay\"\n\nexport interface IKeyPressInfo {\n    timeInMilliseconds: number\n    key: string\n}\n\nconst EmptyArray: IKeyPressInfo[] = []\n\n// This is the total 'size'. For example, if this value is 1000,\n// we will show all key presses over the last 1000ms (1s)\nexport const WindowToShowInMilliseconds = 1000\n\n// This is the size to 'group' key presses - any keys pressed\n// within this timeframe will be grouped together in a box,\n// instead of having their own box\nexport const WindowToGroupInMilliseconds = 200\n\n// Keys coming quicker than the 'DupWindow' will be removed\n// This is somewhat of a hack, as there is a bug in the input\n// resolver pipeline where they can be called multiple times\nexport const DupWindow = 10\n\nexport interface KeyDisplayerState {\n    keys: IKeyPressInfo[]\n    currentTime: number\n}\n\nconst DefaultKeyDisplayerState: KeyDisplayerState = {\n    keys: EmptyArray,\n    currentTime: -1,\n}\n\nexport type KeyDisplayerAction =\n    | {\n          type: \"ADD_KEY\"\n          key: string\n          timeInMilliseconds: number\n      }\n    | {\n          type: \"UPDATE_TIME\"\n          time: number\n      }\n    | { type: \"RESET\" }\n\nexport const reducer: Reducer<KeyDisplayerState> = (\n    state: KeyDisplayerState = DefaultKeyDisplayerState,\n    action: KeyDisplayerAction,\n) => {\n    switch (action.type) {\n        case \"ADD_KEY\":\n            return {\n                ...state,\n                keys: [\n                    ...state.keys,\n                    { key: action.key, timeInMilliseconds: action.timeInMilliseconds },\n                ],\n            }\n        case \"UPDATE_TIME\":\n            return {\n                ...state,\n                currentTime: action.time,\n                keys: state.keys.filter(\n                    key => key.timeInMilliseconds > action.time - WindowToShowInMilliseconds,\n                ),\n            }\n        case \"RESET\":\n            return DefaultKeyDisplayerState\n        default:\n            return state\n    }\n}\n\nexport const getGroupedKeys = (currentTime: number, keys: IKeyPressInfo[]): IKeyPressInfo[][] => {\n    const activeKeys = keys.sort((a, b) => a.timeInMilliseconds - b.timeInMilliseconds)\n\n    const coalescedKeys = activeKeys.reduce<IKeyPressInfo[][]>(\n        (prev: IKeyPressInfo[][], cur) => {\n            const lastGroup = prev[prev.length - 1]\n            if (lastGroup.length === 0) {\n                return [...prev, [cur]]\n            } else {\n                const lastItemInLastGroup = lastGroup[lastGroup.length - 1]\n                const diffTime = Math.abs(\n                    lastItemInLastGroup.timeInMilliseconds - cur.timeInMilliseconds,\n                )\n\n                if (diffTime < WindowToGroupInMilliseconds) {\n                    // Avoid duplicates..\n                    if (diffTime < DupWindow && lastItemInLastGroup.key === cur.key) {\n                        return prev\n                    }\n\n                    lastGroup.push(cur)\n                    return prev\n                } else {\n                    return [...prev, [cur]]\n                }\n            }\n        },\n        [[]],\n    )\n\n    const sanitizedKeys = coalescedKeys.filter(group => group.length > 0)\n\n    return sanitizedKeys\n}\n\nconst clearKeysAfterDelayEpic: Epic<KeyDisplayerAction, KeyDisplayerState> = (action$, store) =>\n    action$\n        .ofType(\"ADD_KEY\")\n        .delay(WindowToShowInMilliseconds + DupWindow)\n        .map(action => {\n            return {\n                type: \"UPDATE_TIME\",\n                time: new Date().getTime(),\n            } as KeyDisplayerAction\n        })\n\nexport const createStore = (): Store<KeyDisplayerState> => {\n    return createReduxStore(\"KeyDisplayer\", reducer, DefaultKeyDisplayerState, [\n        createEpicMiddleware(clearKeysAfterDelayEpic),\n    ])\n}\n"
  },
  {
    "path": "browser/src/Services/KeyDisplayer/KeyDisplayerView.tsx",
    "content": "/**\n * KeyDisplayer\n *\n * Utility for showing keys while typing\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport styled from \"styled-components\"\n\nconst KeyHeight = 50\nconst Margin = 10\n\nconst KeyWrapper = styled.div`\n    position: absolute;\n    right: 50px;\n    background-color: rgba(0, 0, 0, 0.2);\n    padding: 0px 30px;\n    height: ${KeyHeight}px;\n    line-height: ${KeyHeight}px;\n    font-size: 2em;\n    font-weight: bold;\n    color: white;\n`\n\nimport { getGroupedKeys, IKeyPressInfo, KeyDisplayerState } from \"./KeyDisplayerStore\"\n\nexport interface IKeyDisplayerViewProps {\n    groupedKeys: IKeyPressInfo[][]\n}\n\nexport class KeyDisplayerView extends React.PureComponent<IKeyDisplayerViewProps, {}> {\n    public render(): JSX.Element {\n        const keyElements = this.props.groupedKeys.map((k, idx) => (\n            <KeyWrapper style={{ bottom: KeyHeight + (KeyHeight + Margin) * idx + \"px\" }}>\n                {k.map(keyPress => keyPress.key).join(\" \")}\n            </KeyWrapper>\n        ))\n\n        return <div>{keyElements}</div>\n    }\n}\n\nexport const mapStateToProps = (state: KeyDisplayerState): IKeyDisplayerViewProps => ({\n    groupedKeys: getGroupedKeys(state.currentTime, state.keys),\n})\n\nexport const KeyDisplayerContainer = connect(mapStateToProps)(KeyDisplayerView)\n"
  },
  {
    "path": "browser/src/Services/KeyDisplayer/index.tsx",
    "content": "/**\n * KeyDisplayer\n *\n * Utility for showing keys while typing\n */\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { InputManager } from \"./../InputManager\"\nimport { OverlayManager } from \"./../Overlay\"\n\nexport interface IKeyPressInfo {\n    timeInMilliseconds: number\n    key: string\n}\n\nimport { KeyDisplayer } from \"./KeyDisplayer\"\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n    inputManager: InputManager,\n    overlayManager: OverlayManager,\n) => {\n    const keyDisplayer = new KeyDisplayer(\n        configuration,\n        editorManager,\n        inputManager,\n        overlayManager,\n    )\n\n    commandManager.registerCommand({\n        command: \"keyDisplayer.show\",\n        name: \"Input: Show key presses\",\n        detail: \"Show typed keys in an overlay.\",\n        execute: () => keyDisplayer.start(),\n        enabled: () => !keyDisplayer.isActive,\n    })\n\n    commandManager.registerCommand({\n        command: \"keyDisplayer.hide\",\n        name: \"Input: Hide key presses\",\n        detail: \"Turn off visible typing.\",\n        execute: () => keyDisplayer.end(),\n        enabled: () => keyDisplayer.isActive,\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Language/CodeAction.ts",
    "content": "/**\r\n * CodeAction.ts\r\n *\r\n */\r\n\r\n// import * as os from \"os\"\r\nimport * as types from \"vscode-languageserver-types\"\r\n\r\nimport * as Log from \"oni-core-logging\"\r\n// import { configuration } from \"./../Configuration\"\r\n\r\n// import * as UI from \"./../../UI\"\r\n\r\n// import { contextMenuManager } from \"./../ContextMenu\"\r\nimport * as LanguageManager from \"./LanguageManager\"\r\n\r\nimport { editorManager } from \"./../EditorManager\"\r\n\r\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\r\n\r\n// const codeActionsContextMenu = contextMenuManager.create()\r\n\r\n// let lastFileInfo: any = {}\r\n\r\n// codeActionsContextMenu.onItemSelected.subscribe(async (selectedItem) => {\r\n\r\n//     const commandName = selectedItem.data\r\n//     const languageManager = LanguageManager.getInstance()\r\n//     await languageManager.sendLanguageServerRequest(lastFileInfo.language, lastFileInfo.filePath, \"workspace/executeCommand\", { command: commandName })\r\n// })\r\n\r\n// export const expandCodeActions = async () => {\r\n\r\n//     const commands = await getCodeActions()\r\n//     if (!commands || !commands.length) {\r\n//         return\r\n//     }\r\n\r\n//     const mapCommandsToItem = (command: types.Command, idx: number) => ({\r\n//         label: command.title,\r\n//         icon: \"lightbulb-o\",\r\n//         data: command.command,\r\n//     })\r\n\r\n//     const contextMenuItems = commands.map(mapCommandsToItem)\r\n\r\n//     codeActionsContextMenu.show(contextMenuItems)\r\n// }\r\n\r\nexport const getCodeActions = async (): Promise<types.Command[]> => {\r\n    const buffer = editorManager.activeEditor.activeBuffer\r\n\r\n    const { language, filePath } = buffer\r\n    const range = await buffer.getSelectionRange()\r\n\r\n    if (!range) {\r\n        return null\r\n    }\r\n\r\n    const languageManager = LanguageManager.getInstance()\r\n    if (languageManager.isLanguageServerAvailable(language)) {\r\n        let result: types.Command[] = null\r\n        try {\r\n            result = await languageManager.sendLanguageServerRequest(\r\n                language,\r\n                filePath,\r\n                \"textDocument/codeAction\",\r\n                Helpers.eventContextToCodeActionParams(filePath, range),\r\n            )\r\n        } catch (ex) {\r\n            Log.verbose(ex)\r\n        }\r\n\r\n        if (!result) {\r\n            return null\r\n        }\r\n\r\n        // lastFileInfo = {\r\n        //     language,\r\n        //     filePath,\r\n        // }\r\n\r\n        return result\r\n    } else {\r\n        return null\r\n    }\r\n}\r\n"
  },
  {
    "path": "browser/src/Services/Language/DefinitionRequestor.ts",
    "content": "/**\n * DefinitionRequestor.ts\n *\n * Abstraction over the action of requesting a definition\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { LanguageManager } from \"./LanguageManager\"\n\nexport interface IDefinitionResult {\n    location: types.Location | null\n    token: Oni.IToken | null\n}\n\nexport interface IDefinitionRequestor {\n    getDefinition(\n        fileLanguage: string,\n        filePath: string,\n        line: number,\n        column: number,\n    ): Promise<IDefinitionResult>\n}\n\nexport class LanguageServiceDefinitionRequestor {\n    constructor(private _languageManager: LanguageManager, private _editor: Oni.Editor) {}\n\n    public async getDefinition(\n        fileLanguage: string,\n        filePath: string,\n        line: number,\n        column: number,\n    ): Promise<IDefinitionResult> {\n        const args = { ...Helpers.createTextDocumentPositionParams(filePath, line, column) }\n\n        const token: Oni.IToken = await this._editor.activeBuffer.getTokenAt(line, column)\n\n        if (!token) {\n            return {\n                token: null,\n                location: null,\n            }\n        }\n\n        let result: types.Location | types.Location[] = null\n        try {\n            result = await this._languageManager.sendLanguageServerRequest(\n                fileLanguage,\n                filePath,\n                \"textDocument/definition\",\n                args,\n            )\n        } catch (ex) {\n            Log.warn(ex)\n        }\n\n        return {\n            location: getFirstLocationFromArray(result),\n            token,\n        }\n    }\n}\n\nexport const getFirstLocationFromArray = (\n    result: types.Location | types.Location[],\n): types.Location => {\n    if (!result) {\n        return null\n    }\n\n    if (result instanceof Array) {\n        if (!result.length) {\n            return null\n        }\n        return result[0]\n    }\n\n    return result\n}\n"
  },
  {
    "path": "browser/src/Services/Language/Edits.ts",
    "content": "/**\n * Edits.ts\n *\n * Helpers to work with TextEdits and buffer manipulation\n */\n\nimport * as orderBy from \"lodash/orderBy\"\nimport * as types from \"vscode-languageserver-types\"\n\nexport const sortTextEdits = (edits: types.TextEdit[]): types.TextEdit[] => {\n    const sortedEdits = orderBy(\n        edits,\n        [e => e.range.start.line, e => e.range.start.character],\n        [\"desc\", \"desc\"],\n    )\n    return sortedEdits\n}\n\nexport const convertTextDocumentChangesToFileMap = (\n    edits: Array<types.TextDocumentEdit | types.CreateFile | types.RenameFile | types.DeleteFile>,\n): { [fileUri: string]: types.TextEdit[] } => {\n    if (!edits) {\n        return {}\n    }\n\n    return edits.reduce((prev, curr) => {\n        if (!(\"textDocument\" in curr)) {\n            return prev\n        }\n        return {\n            ...prev,\n            [curr.textDocument.uri]: edits,\n        }\n    }, {})\n}\n"
  },
  {
    "path": "browser/src/Services/Language/FindAllReferences.ts",
    "content": "/**\n * QuickInfo.ts\n *\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { INeovimInstance } from \"./../../neovim\"\n\nimport { editorManager } from \"./../EditorManager\"\nimport * as LanguageManager from \"./LanguageManager\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\n// TODO:\n// - Factor out event context to something simpler\n// - Remove plugin manager\nexport const findAllReferences = async () => {\n    const activeEditor = editorManager.activeEditor\n\n    if (!activeEditor) {\n        return\n    }\n\n    const activeBuffer = activeEditor.activeBuffer\n\n    if (!activeBuffer) {\n        return\n    }\n\n    const languageManager = LanguageManager.getInstance()\n    if (languageManager.isLanguageServerAvailable(activeBuffer.language)) {\n        const args = {\n            ...Helpers.bufferToTextDocumentPositionParams(activeBuffer),\n            context: {\n                includeDeclaration: true,\n            },\n        }\n\n        const { line, column } = activeBuffer.cursor\n        const token = await activeBuffer.getTokenAt(line, column)\n        const result: types.Location[] = await languageManager.sendLanguageServerRequest(\n            activeBuffer.language,\n            activeBuffer.filePath,\n            \"textDocument/references\",\n            args,\n        )\n        showReferencesInQuickFix(token.tokenName, result, activeEditor.neovim as any)\n    }\n}\n\nexport const showReferencesInQuickFix = async (\n    token: string,\n    locations: types.Location[],\n    neovimInstance: INeovimInstance,\n) => {\n    const convertToOneIndexedForQuickFix = (location: types.Location) => ({\n        filename: Helpers.unwrapFileUriPath(location.uri),\n        lnum: location.range.start.line + 1,\n        col: location.range.start.character + 1,\n        text: token,\n    })\n\n    const quickFixItems = locations.map(item => convertToOneIndexedForQuickFix(item))\n\n    neovimInstance.quickFix.setqflist(quickFixItems, ` Find All References: ${token}`)\n    neovimInstance.command(\"copen\")\n    neovimInstance.command(`execute \"normal! /${token}\\\\<cr>\"`)\n}\n"
  },
  {
    "path": "browser/src/Services/Language/Formatting.ts",
    "content": "/**\n * Rename.tsx\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { editorManager } from \"./../EditorManager\"\n\nimport * as LanguageManager from \"./LanguageManager\"\n\nexport const format = async () => {\n    const activeBuffer = editorManager.activeEditor.activeBuffer\n\n    const capabilities = await LanguageManager.getInstance().getCapabilitiesForLanguage(\n        activeBuffer.language,\n    )\n\n    if (capabilities.documentFormattingProvider) {\n        await formatDocument()\n    } else if (capabilities.documentRangeFormattingProvider) {\n        await rangeFormatDocument()\n    } else {\n        Log.warn(\"No formatting provider available\")\n    }\n}\n\nexport const formatDocument = async () => {\n    const activeBuffer = editorManager.activeEditor.activeBuffer\n\n    const args = {\n        textDocument: {\n            uri: Helpers.wrapPathInFileUri(activeBuffer.filePath),\n        },\n    }\n\n    let result: types.TextEdit[] = null\n    try {\n        result = await LanguageManager.getInstance().sendLanguageServerRequest(\n            activeBuffer.language,\n            activeBuffer.filePath,\n            \"textDocument/formatting\",\n            args,\n        )\n    } catch (ex) {\n        Log.warn(ex)\n    }\n\n    if (result) {\n        await activeBuffer.applyTextEdits(result)\n    }\n}\n\nexport const rangeFormatDocument = async () => {\n    const activeBuffer = editorManager.activeEditor.activeBuffer\n\n    const args = {\n        textDocument: {\n            uri: Helpers.wrapPathInFileUri(activeBuffer.filePath),\n        },\n        range: types.Range.create(0, 0, activeBuffer.lineCount - 1, 0),\n    }\n\n    let result: types.TextEdit[] = null\n    try {\n        result = await LanguageManager.getInstance().sendLanguageServerRequest(\n            activeBuffer.language,\n            activeBuffer.filePath,\n            \"textDocument/rangeFormatting\",\n            args,\n        )\n    } catch (ex) {\n        Log.warn(ex)\n    }\n\n    if (result) {\n        await activeBuffer.applyTextEdits(result)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/HoverRequestor.ts",
    "content": "/**\n * HoverRequestor.ts\n *\n * Abstraction over the action of requesting a definition\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { LanguageManager } from \"./LanguageManager\"\n\nimport * as Diagnostics from \"./../Diagnostics\"\n\nexport interface IHoverResult {\n    hover: types.Hover\n    errors: types.Diagnostic[]\n}\n\nexport interface IHoverRequestor {\n    getHover(\n        fileLanguage: string,\n        filePath: string,\n        line: number,\n        column: number,\n    ): Promise<IHoverResult>\n}\n\nexport class LanguageServiceHoverRequestor {\n    constructor(private _languageManager: LanguageManager) {}\n\n    public async getHover(\n        language: string,\n        filePath: string,\n        line: number,\n        column: number,\n    ): Promise<IHoverResult> {\n        const args = { ...Helpers.createTextDocumentPositionParams(filePath, line, column) }\n\n        let result: types.Hover = null\n\n        if (this._languageManager.isLanguageServerAvailable(language)) {\n            try {\n                result = await this._languageManager.sendLanguageServerRequest(\n                    language,\n                    filePath,\n                    \"textDocument/hover\",\n                    args,\n                )\n            } catch (ex) {\n                Log.warn(ex)\n            }\n        }\n\n        const latestErrors = Diagnostics.getInstance().getErrorsForPosition(filePath, line, column)\n\n        return {\n            hover: result,\n            errors: latestErrors,\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageClient.ts",
    "content": "import * as rpc from \"vscode-jsonrpc\"\n\nimport * as Log from \"oni-core-logging\"\nimport { Event } from \"oni-types\"\n\nimport { ILanguageClientProcess } from \"./LanguageClientProcess\"\nimport { PromiseQueue } from \"./PromiseQueue\"\nimport { IServerCapabilities } from \"./ServerCapabilities\"\n\nimport * as LanguageClientTypes from \"./LanguageClientTypes\"\n\nexport interface ILanguageClient {\n    serverCapabilities: IServerCapabilities\n    subscribe(notificationName: string, evt: Event<any>): void\n    handleRequest(requestName: string, handler: LanguageClientTypes.RequestHandler): void\n\n    sendRequest<T>(\n        fileName: string,\n        requestName: string,\n        protocolArguments: LanguageClientTypes.NotificationValueOrThunk,\n    ): Promise<T>\n    sendNotification(\n        fileName: string,\n        notificationName: string,\n        protocolArguments: LanguageClientTypes.NotificationValueOrThunk,\n    ): void\n}\n\nexport class LanguageClient implements ILanguageClient {\n    private _promiseQueue = new PromiseQueue()\n\n    private _connection: rpc.MessageConnection\n    private _subscriptions: { [key: string]: Event<any> } = {}\n    private _requestHandlers: { [key: string]: LanguageClientTypes.RequestHandler } = {}\n\n    public get serverCapabilities(): IServerCapabilities {\n        return this._languageClientProcess.serverCapabilities\n    }\n\n    constructor(private _language: string, private _languageClientProcess: ILanguageClientProcess) {\n        this._languageClientProcess.onConnectionChanged.subscribe(\n            (newConnection: rpc.MessageConnection) => {\n                this._connection = newConnection\n\n                Object.keys(this._subscriptions).forEach(notification => {\n                    const evt = this._subscriptions[notification]\n                    this._connection.onNotification(notification, (args: any) => {\n                        evt.dispatch({\n                            language: this._language,\n                            payload: args,\n                        })\n                    })\n                })\n\n                Object.keys(this._requestHandlers).forEach(request => {\n                    const handler = this._requestHandlers[request]\n                    if (handler) {\n                        this._connection.onRequest(request, handler)\n                    }\n                })\n            },\n        )\n    }\n\n    public subscribe(notificationName: string, evt: Event<any>) {\n        if (this._connection) {\n            this._connection.onNotification(notificationName, (args: any) => {\n                evt.dispatch({\n                    language: this._language,\n                    payload: args,\n                })\n            })\n        }\n\n        this._subscriptions[notificationName] = evt\n    }\n\n    public handleRequest(requestName: string, handler: (payload: any) => Promise<any>): void {\n        if (this._requestHandlers[requestName]) {\n            Log.error(\"Only one handler is allowed\")\n        }\n\n        if (this._connection) {\n            this._connection.onRequest(requestName, handler)\n        }\n\n        this._requestHandlers[requestName] = handler\n    }\n\n    public sendRequest<T>(\n        fileName: string,\n        requestName: string,\n        protocolArguments: LanguageClientTypes.NotificationValueOrThunk,\n    ): Promise<T> {\n        return this._promiseQueue.enqueuePromise<T>(async () => {\n            this._connection = await this._languageClientProcess.ensureActive(fileName)\n\n            const args = await LanguageClientTypes.unwrapThunkOrValue(\n                protocolArguments,\n                this.serverCapabilities,\n            )\n\n            logInfo(`Request ${requestName} - ${fileName}: start`)\n            const result = await this._connection.sendRequest<T>(requestName, args)\n            logInfo(`Request ${requestName} - ${fileName}: end`)\n            return result\n        })\n    }\n\n    public sendNotification(\n        fileName: string,\n        notificationName: string,\n        protocolArguments: LanguageClientTypes.NotificationValueOrThunk,\n    ): void {\n        this._promiseQueue.enqueuePromise(async () => {\n            this._connection = await this._languageClientProcess.ensureActive(fileName)\n\n            const args = await LanguageClientTypes.unwrapThunkOrValue(\n                protocolArguments,\n                this.serverCapabilities,\n            )\n\n            logInfo(`Notification ${notificationName} - ${fileName}: start`)\n\n            await this._connection.sendNotification(notificationName, args)\n\n            logInfo(`Notification ${notificationName} - ${fileName}: end`)\n        })\n    }\n}\n\nconst logInfo = (msg: string): void => {\n    Log.info(\"[Language Client] \" + msg)\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageClientProcess.ts",
    "content": "/**\n * LanguageClientProcess.ts\n *\n * Responsible for the lifecycle of the language server process, including:\n *  - Creating the language process\n *  - Restarting language process if working path / rootPath differ\n *  - Sending initialization\n *  - Managing the connection\n *  - Getting server capabilities\n */\n\nimport * as path from \"path\"\n\nimport { ChildProcess } from \"child_process\"\nimport * as rpc from \"vscode-jsonrpc\"\n\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { normalizePath } from \"./../../Utility\"\n\nimport { LanguageClientLogger } from \"./../../Plugins/Api/LanguageClient/LanguageClientLogger\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport Process from \"./../../Plugins/Api/Process\"\n\nimport { IServerCapabilities } from \"./ServerCapabilities\"\n\nexport interface ILanguageClientProcess {\n    onConnectionChanged: IEvent<rpc.MessageConnection>\n    serverCapabilities: IServerCapabilities\n\n    ensureActive(fileName: string): Promise<rpc.MessageConnection>\n}\n\nexport type PathResolver = (filePath: string) => Promise<string>\n\nexport interface ServerRunOptions {\n    /**\n     * Specify `command` to use a shell command to spawn a process\n     */\n    command?: string\n\n    /**\n     * Specify `module` to run a JavaScript module\n     */\n    module?: string\n\n    /**\n     * Arguments to pass to the language servicew\n     */\n    args?: string[]\n\n    workingDirectory?: PathResolver\n}\n\nexport interface InitializationOptions {\n    rootPath: PathResolver\n}\n\nexport class LanguageClientProcess {\n    private _process: ChildProcess\n    private _connection: rpc.MessageConnection\n    private _onConnectionChangedEvent = new Event<rpc.MessageConnection>()\n\n    private _lastWorkingDirectory: string = null\n    private _lastRootPath: string = null\n    private _serverCapabilities: IServerCapabilities = {}\n\n    // Notifies when the connection has changed (due to process restart)\n    // This allows consumers to re-subscribe to events\n    public get onConnectionChanged(): IEvent<rpc.MessageConnection> {\n        return this._onConnectionChangedEvent\n    }\n\n    public get serverCapabilities(): IServerCapabilities {\n        return this._serverCapabilities\n    }\n\n    constructor(\n        private _serverOptions: ServerRunOptions,\n        private _initializationOptions: InitializationOptions,\n        private _configuration: any = null,\n    ) {}\n\n    public async ensureActive(fileName: string): Promise<rpc.MessageConnection> {\n        const rootDir = normalizePath(path.dirname(fileName))\n        const workingDirectory = await this._serverOptions.workingDirectory(rootDir)\n        const rootPath = await this._initializationOptions.rootPath(rootDir)\n\n        const shouldRestartServer =\n            workingDirectory !== this._lastWorkingDirectory ||\n            this._lastRootPath !== rootPath ||\n            !this._connection\n\n        if (shouldRestartServer) {\n            this._end()\n            await this._start(workingDirectory, rootPath)\n            return this._connection\n        } else {\n            return this._connection\n        }\n    }\n\n    private async _start(workingDirectory: string, rootPath: string): Promise<void> {\n        const args = this._serverOptions.args || []\n\n        const options = {\n            cwd: workingDirectory || process.cwd(),\n        }\n\n        if (this._serverOptions.command) {\n            Log.info(\n                `[LanguageClientProcess]: Starting process via '${this._serverOptions.command}'`,\n            )\n            this._process = await Process.spawnProcess(this._serverOptions.command, args, options)\n        } else if (this._serverOptions.module) {\n            Log.info(\n                `[LanguageClientProcess]: Starting process via node script '${\n                    this._serverOptions.module\n                }'`,\n            )\n            this._process = await Process.spawnNodeScript(this._serverOptions.module, args, options)\n        } else {\n            throw new Error(\"A command or module must be specified to start the server\")\n        }\n\n        if (!this._process || !this._process.pid) {\n            throw new Error(\"Unable to start language server process\")\n        }\n\n        Log.info(`[LanguageClientProcess]: Started process ${this._process.pid}`)\n\n        this._process.stderr.on(\"data\", msg => {\n            Log.info(`[LANGUAGE CLIENT - STDERR]: ${msg}`)\n            // this._statusBar.setStatus(LanguageClientState.Error)\n        })\n\n        this._lastWorkingDirectory = workingDirectory\n        this._lastRootPath = rootPath\n\n        this._connection = rpc.createMessageConnection(\n            new rpc.StreamMessageReader(this._process.stdout) as any,\n            new rpc.StreamMessageWriter(this._process.stdin) as any,\n            new LanguageClientLogger(),\n        )\n\n        this._onConnectionChangedEvent.dispatch(this._connection)\n\n        this._connection.listen()\n\n        const NoDynamicRegistration = {\n            dynamicRegistration: false,\n        }\n\n        const SupportedMarkup = [\"plaintext\"]\n\n        const oniLanguageClientParams = {\n            clientName: \"oni\",\n            rootPath,\n            rootUri: Helpers.wrapPathInFileUri(rootPath),\n            capabilities: {\n                workspace: {\n                    applyEdit: true,\n                    workspaceEdit: {\n                        documentChanges: false,\n                    },\n                    didChangeConfiguration: NoDynamicRegistration,\n                    didChangeWatchedFiles: NoDynamicRegistration,\n                    symbol: NoDynamicRegistration,\n                    executeCommand: NoDynamicRegistration,\n                },\n                textDocument: {\n                    synchronization: {\n                        dynamicRegistration: false,\n                        willSave: false,\n                        willSaveWaitUntil: false,\n                        didSave: true,\n                    },\n                    completion: {\n                        dynamicRegistration: false,\n                        completionItem: {\n                            snippetSupport: true,\n                            commitCharactersSupport: true,\n                            documentationFormat: SupportedMarkup,\n                        },\n                        completionItemKind: {},\n                        contextSupport: false,\n                    },\n                    hover: {\n                        dynamicRegistration: false,\n                        contentFormat: SupportedMarkup,\n                    },\n                    signatureHelp: {\n                        dynamicRegistration: false,\n                        signatureInformation: {\n                            documentationFormat: SupportedMarkup,\n                        },\n                    },\n                    references: NoDynamicRegistration,\n                    documentSymbol: NoDynamicRegistration,\n                    formatting: NoDynamicRegistration,\n                    rangeFormatting: NoDynamicRegistration,\n                    definition: NoDynamicRegistration,\n                    codeAction: NoDynamicRegistration,\n                    codeLens: NoDynamicRegistration,\n                    rename: NoDynamicRegistration,\n                },\n            },\n        }\n\n        try {\n            const response: any = await this._connection.sendRequest(\n                \"initialize\",\n                oniLanguageClientParams,\n            )\n            Log.info(`[LanguageClientManager]: Initialized`)\n            if (response && response.capabilities) {\n                this._serverCapabilities = response.capabilities\n            }\n\n            if (this._configuration) {\n                Log.verbose(\"[LanguageClientProcess]: Sending configuration\")\n                this._connection.sendNotification(\"workspace/didChangeConfiguration\", {\n                    settings: this._configuration,\n                })\n            }\n        } catch (ex) {\n            Log.error(ex)\n        }\n    }\n\n    private _end(): void {\n        Log.info(\"[LanguageClientProcess] Ending language server session\")\n\n        if (this._connection) {\n            this._connection.dispose()\n            this._connection = null\n        }\n\n        if (this._process) {\n            this._process.kill()\n            this._process = null\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageClientStatusBar.tsx",
    "content": "/**\n * LanguageClientStatusBar.tsx\n *\n * Implements status bar for Oni\n */\n\nimport * as electron from \"electron\"\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\n\nimport { Icon } from \"./../../UI/Icon\"\n\nexport class LanguageClientStatusBar {\n    private _item: Oni.StatusBarItem\n    private _fileType: string\n\n    constructor(private _oni: Oni.Plugin.Api) {\n        this._item = this._oni.statusBar.createItem(0, \"oni.status.fileType\")\n    }\n\n    public show(fileType: string): void {\n        this._fileType = fileType\n        this._item.setContents(\n            <StatusBarRenderer\n                state={LanguageClientState.NotAvailable}\n                language={this._fileType}\n            />,\n        )\n        this._item.show()\n    }\n\n    public setStatus(status: LanguageClientState): void {\n        this._item.setContents(<StatusBarRenderer state={status} language={this._fileType} />)\n    }\n\n    public hide(): void {\n        this._item.hide()\n    }\n}\n\nexport enum LanguageClientState {\n    NotAvailable = 0,\n    Initializing,\n    Initialized,\n    Active,\n    Error,\n}\n\nconst SpinnerIcon = \"circle-o-notch\"\nconst ConnectedIcon = \"bolt\"\nconst ErrorIcon = \"exclamation-circle\"\n\ninterface StatusBarRendererProps {\n    state: LanguageClientState\n    language: string\n}\n\nconst getIconFromStatus = (status: LanguageClientState) => {\n    switch (status) {\n        case LanguageClientState.NotAvailable:\n            return null\n        case LanguageClientState.Initializing:\n            return SpinnerIcon\n        case LanguageClientState.Error:\n            return ErrorIcon\n        default:\n            return ConnectedIcon\n    }\n}\n\nconst getClassNameFromstatus = (status: LanguageClientState) => {\n    switch (status) {\n        case LanguageClientState.Initializing:\n            return \"rotate-animation\"\n        default:\n            return \"\"\n    }\n}\n\nconst StatusBarRenderer = (props: StatusBarRendererProps) => {\n    const containerStyle: React.CSSProperties = {\n        display: \"flex\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        height: \"100%\",\n        backgroundColor: \"rgb(35, 35, 35)\",\n        color: \"rgb(200, 200, 200)\",\n        paddingRight: \"8px\",\n        paddingLeft: \"8px\",\n    }\n\n    const iconStyle: React.CSSProperties = {\n        paddingRight: \"6px\",\n        minWidth: \"14px\",\n        textAlign: \"center\",\n    }\n\n    const openDevTools = () => {\n        electron.remote.getCurrentWindow().webContents.openDevTools()\n    }\n\n    const onClick = props.state === LanguageClientState.Error ? openDevTools : null\n\n    const iconName = getIconFromStatus(props.state)\n\n    const icon = iconName ? (\n        <span style={iconStyle}>\n            <Icon name={iconName} className={getClassNameFromstatus(props.state)} />\n        </span>\n    ) : null\n\n    return (\n        <div style={containerStyle} onClick={onClick}>\n            {icon}\n            <span>{props.language}</span>\n        </div>\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageClientTypes.ts",
    "content": "import * as types from \"vscode-languageserver-types\"\n\nimport { IServerCapabilities } from \"./ServerCapabilities\"\n\nexport type NotificationFunction = (capabilities: IServerCapabilities) => any\nexport type NotificationFunctionWithPromise = (capabilities: IServerCapabilities) => Promise<any>\nexport type NotificationValueOrThunk = NotificationFunction | NotificationFunctionWithPromise | any\n\nexport type RequestHandler = (payload: any) => Promise<any>\n\nexport interface IResultWithPosition<T> {\n    result: T\n    position: types.Position\n}\n\nexport const unwrapThunkOrValue = (val: NotificationValueOrThunk, args: any): Promise<any> => {\n    if (typeof val !== \"function\") {\n        return Promise.resolve(val)\n    } else {\n        const returnValue = val(args)\n        if (typeof returnValue.then === \"function\") {\n            return Promise.resolve(returnValue)\n        } else {\n            return returnValue\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageConfiguration.ts",
    "content": "/**\n * LanguageConfiguration.ts\n *\n * Helper for registering language client information from config\n */\n\nimport * as Log from \"oni-core-logging\"\n\nimport { LanguageClient } from \"./LanguageClient\"\nimport {\n    InitializationOptions,\n    LanguageClientProcess,\n    ServerRunOptions,\n} from \"./LanguageClientProcess\"\nimport * as LanguageManager from \"./LanguageManager\"\n\nimport { getRootProjectFileFunc } from \"./../../Utility\"\n\nexport interface ILightweightLanguageConfiguration {\n    languageServer?: ILightweightLanguageServerConfiguration\n}\n\nexport interface ILightweightLanguageServerConfiguration {\n    arguments?: string[]\n    command?: string\n    rootFiles?: string[]\n    configuration?: any\n}\n\nexport const createLanguageClientsFromConfiguration = (configurationValues: {\n    [key: string]: any\n}) => {\n    const languageInfo = expandLanguageConfiguration(configurationValues)\n    const languages = Object.keys(languageInfo)\n\n    languages.forEach(lang => {\n        createLanguageClientFromConfig(lang, languageInfo[lang])\n    })\n}\n\nconst expandLanguageConfiguration = (configuration: { [key: string]: any }) => {\n    // Filter for all `language.` keys, ie `language.go.languageServerCommand`\n    const keys = Object.keys(configuration).filter(k => k.indexOf(\"language.\") === 0)\n\n    if (keys.length === 0) {\n        return {}\n    }\n\n    const expanded = keys.reduce<any>((prev, current) => {\n        const newValue = expandConfigurationSetting(\n            prev,\n            current.split(\".\"),\n            configuration[current],\n        )\n        return newValue\n    }, {})\n\n    return expanded.language\n}\n\nconst expandConfigurationSetting = (\n    rootObject: any,\n    configurationPath: string[],\n    value: string,\n): any => {\n    if (!configurationPath || !configurationPath.length) {\n        return value\n    }\n\n    const [currentPath, ...remaining] = configurationPath\n\n    const currentObject = rootObject[currentPath] || {}\n\n    return {\n        ...rootObject,\n        [currentPath]: expandConfigurationSetting(currentObject, remaining, value),\n    }\n}\n\nconst simplePathResolver = (filePath: string) => Promise.resolve(filePath)\n\nconst createLanguageClientFromConfig = (\n    language: string,\n    config: ILightweightLanguageConfiguration,\n): void => {\n    if (!config || !config.languageServer || !config.languageServer.command) {\n        return\n    }\n\n    const lightweightCommand = config.languageServer.command\n    const rootFiles = config.languageServer.rootFiles\n    const args = config.languageServer.arguments || []\n    const configuration = config.languageServer.configuration || null\n\n    Log.info(\n        `[Language Manager - Config] Registering info for language: ${language} - command: ${\n            config.languageServer.command\n        }`,\n    )\n\n    const commandOrModule = lightweightCommand.endsWith(\".js\")\n        ? { module: lightweightCommand }\n        : { command: lightweightCommand }\n\n    let pathResolver = simplePathResolver\n\n    if (rootFiles) {\n        pathResolver = getRootProjectFileFunc(rootFiles)\n    }\n\n    const serverRunOptions: ServerRunOptions = {\n        ...commandOrModule,\n        args,\n        workingDirectory: pathResolver,\n    }\n\n    const initializationOptions: InitializationOptions = {\n        rootPath: pathResolver,\n    }\n    const languageClient = new LanguageClient(\n        language,\n        new LanguageClientProcess(serverRunOptions, initializationOptions, configuration),\n    )\n    LanguageManager.getInstance().registerLanguageClient(language, languageClient)\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageEditorIntegration.ts",
    "content": "/**\n * LanguageEditorIntegration\n *\n * Responsible for listening to editor events,\n * and hooking up the language service functionality.\n */\n\nimport { Store, Unsubscribe } from \"redux\"\n\nimport * as Oni from \"oni-api\"\nimport * as OniTypes from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Configuration } from \"./../Configuration\"\n\nimport { LanguageManager } from \"./LanguageManager\"\nimport { createStore, DefaultLanguageState, ILanguageState } from \"./LanguageStore\"\n\nimport {\n    IDefinitionRequestor,\n    IDefinitionResult,\n    LanguageServiceDefinitionRequestor,\n} from \"./DefinitionRequestor\"\nimport { IHoverRequestor, IHoverResult, LanguageServiceHoverRequestor } from \"./HoverRequestor\"\n\nexport class LanguageEditorIntegration implements OniTypes.IDisposable {\n    private _subscriptions: OniTypes.IDisposable[] = []\n    private _store: Store<ILanguageState>\n    private _storeUnsubscribe: Unsubscribe = null\n    private _lastState: ILanguageState = DefaultLanguageState\n\n    private _onShowDefinition: OniTypes.Event<IDefinitionResult> = new OniTypes.Event<\n        IDefinitionResult\n    >()\n    private _onHideDefinition: OniTypes.Event<void> = new OniTypes.Event<void>()\n\n    private _onShowHover: OniTypes.Event<IHoverResult> = new OniTypes.Event<IHoverResult>()\n    private _onHideHover: OniTypes.Event<void> = new OniTypes.Event<void>()\n\n    public get onShowDefinition(): OniTypes.IEvent<IDefinitionResult> {\n        return this._onShowDefinition\n    }\n    public get onHideDefinition(): OniTypes.IEvent<void> {\n        return this._onHideDefinition\n    }\n\n    public get onShowHover(): OniTypes.IEvent<IHoverResult> {\n        return this._onShowHover\n    }\n    public get onHideHover(): OniTypes.IEvent<void> {\n        return this._onHideHover\n    }\n\n    constructor(\n        private _editor: Oni.Editor,\n        private _configuration: Configuration,\n        private _languageManager?: LanguageManager,\n        private _definitionRequestor?: IDefinitionRequestor,\n        private _hoverRequestor?: IHoverRequestor,\n    ) {\n        this._definitionRequestor =\n            this._definitionRequestor ||\n            new LanguageServiceDefinitionRequestor(this._languageManager, this._editor)\n        this._hoverRequestor =\n            this._hoverRequestor || new LanguageServiceHoverRequestor(this._languageManager)\n\n        this._store = createStore(\n            this._configuration,\n            this._hoverRequestor,\n            this._definitionRequestor,\n        )\n\n        this._subscriptions = [\n            this._editor.onModeChanged.subscribe((newMode: string) => {\n                this._store.dispatch({\n                    type: \"MODE_CHANGED\",\n                    mode: newMode,\n                })\n            }),\n\n            this._editor.onBufferEnter.subscribe((bufferEvent: Oni.EditorBufferEventArgs) => {\n                this._store.dispatch({\n                    type: \"BUFFER_ENTER\",\n                    filePath: bufferEvent.filePath,\n                    language: bufferEvent.language,\n                })\n            }),\n            this._editor.onCursorMoved.subscribe((cursorMoveEvent: Oni.Cursor) => {\n                this._store.dispatch({\n                    type: \"CURSOR_MOVED\",\n                    line: cursorMoveEvent.line,\n                    column: cursorMoveEvent.column,\n                })\n            }),\n            this._editor.onBufferScrolled.subscribe(scrollEvent => {\n                this._onHideHover.dispatch()\n                this._onHideDefinition.dispatch()\n            }),\n        ]\n\n        this._storeUnsubscribe = this._store.subscribe(() =>\n            this._onStateUpdate(this._store.getState()),\n        )\n    }\n\n    // Explicit gesture to show hover - ignores the setting\n    public showHover(): void {\n        const state = this._store.getState()\n        this._store.dispatch({\n            type: \"HOVER_QUERY\",\n            location: {\n                filePath: state.activeBuffer.filePath,\n                language: state.activeBuffer.language,\n                line: state.cursor.line,\n                column: state.cursor.column,\n            },\n        })\n    }\n\n    public dispose(): void {\n        if (this._subscriptions && this._subscriptions.length) {\n            this._subscriptions.forEach(disposable => disposable.dispose())\n            this._subscriptions = null\n        }\n\n        if (this._storeUnsubscribe) {\n            this._storeUnsubscribe()\n            this._storeUnsubscribe = null\n        }\n    }\n\n    private _onStateUpdate(newState: ILanguageState): void {\n        const newLocationResult = getLocationFromState(newState)\n        const lastLocationResult = getLocationFromState(this._lastState)\n        if (newLocationResult && !lastLocationResult) {\n            this._onShowDefinition.dispatch(newState.definitionResult.result)\n        }\n\n        if (!newLocationResult && lastLocationResult) {\n            this._onHideDefinition.dispatch()\n        }\n\n        if (newState.hoverResult.result && !this._lastState.hoverResult.result) {\n            this._onShowHover.dispatch(newState.hoverResult.result)\n        }\n\n        if (!newState.hoverResult.result && this._lastState.hoverResult.result) {\n            this._onHideHover.dispatch()\n        }\n\n        this._lastState = newState\n    }\n}\n\nconst getLocationFromState = (state: ILanguageState): types.Location => {\n    if (\n        state &&\n        state.definitionResult &&\n        state.definitionResult.result &&\n        state.definitionResult.result.location\n    ) {\n        return state.definitionResult.result.location\n    } else {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageManager.ts",
    "content": "/**\n * LanguageManager\n *\n * Service for integrating language services, like:\n *  - Language server protocol\n *  - Synchronizing language configuration\n *  - Handling custom syntax (TextMate themes)\n */\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IDisposable } from \"oni-types\"\n\nimport { ILanguageClient } from \"./LanguageClient\"\nimport * as LanguageClientTypes from \"./LanguageClientTypes\"\nimport { IServerCapabilities } from \"./ServerCapabilities\"\n\nimport * as Capabilities from \"./../../Plugins/Api/Capabilities\"\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\nimport { LanguageClientState, LanguageClientStatusBar } from \"./LanguageClientStatusBar\"\n\nimport { listenForWorkspaceEdits } from \"./Workspace\"\n\nimport * as Utility from \"./../../Utility\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nexport interface ILanguageServerNotificationResponse {\n    language: string\n    payload: any\n}\n\nexport class LanguageManager {\n    private _languageServerInfo: { [language: string]: ILanguageClient } = {}\n    private _notificationSubscriptions: { [notificationMessage: string]: Event<any> } = {}\n    private _requestHandlers: { [request: string]: LanguageClientTypes.RequestHandler } = {}\n    private _languageClientStatusBar: LanguageClientStatusBar\n    private _currentTrackedFile: string = null\n\n    constructor(private _oni: Oni.Plugin.Api) {\n        this._languageClientStatusBar = new LanguageClientStatusBar(_oni)\n\n        this._oni.editors.anyEditor.onBufferEnter.subscribe(async () => this._onBufferEnter())\n\n        this._oni.editors.anyEditor.onBufferLeave.subscribe(\n            (bufferInfo: Oni.EditorBufferEventArgs) => {\n                const { language, filePath } = bufferInfo\n\n                if (this._currentTrackedFile !== filePath) {\n                    return\n                }\n\n                this.sendLanguageServerNotification(\n                    language,\n                    filePath,\n                    \"textDocument/didClose\",\n                    Helpers.pathToTextDocumentIdentifierParms(filePath),\n                )\n            },\n        )\n\n        this._oni.editors.anyEditor.onBufferChanged.subscribe(\n            async (change: Oni.EditorBufferChangedEventArgs) => {\n                const { language, filePath } = change.buffer\n\n                if (this._currentTrackedFile !== filePath) {\n                    return\n                }\n\n                const sendBufferThunk = async (capabilities: IServerCapabilities) => {\n                    const textDocument = {\n                        uri: Helpers.wrapPathInFileUri(filePath),\n                        version: change.buffer.version,\n                    }\n\n                    // If the service supports incremental capabilities, just pass it directly\n                    if (capabilities.textDocumentSync === 2) {\n                        return {\n                            textDocument,\n                            contentChanges: change.contentChanges,\n                        }\n                        // Otherwise, get the whole buffer and send it up\n                    } else {\n                        const allBufferLines = await change.buffer.getLines()\n\n                        return {\n                            textDocument,\n                            contentChanges: [{ text: allBufferLines.join(os.EOL) }],\n                        }\n                    }\n                }\n\n                this.sendLanguageServerNotification(\n                    language,\n                    filePath,\n                    \"textDocument/didChange\",\n                    sendBufferThunk,\n                )\n            },\n        )\n\n        this._oni.editors.anyEditor.onBufferSaved.subscribe(\n            (bufferInfo: Oni.EditorBufferEventArgs) => {\n                const { language, filePath } = bufferInfo\n\n                if (this._currentTrackedFile !== filePath) {\n                    return\n                }\n\n                this.sendLanguageServerNotification(\n                    language,\n                    filePath,\n                    \"textDocument/didSave\",\n                    Helpers.pathToTextDocumentIdentifierParms(filePath),\n                )\n            },\n        )\n\n        this.subscribeToLanguageServerNotification(\"window/showMessage\", args => {\n            Log.warn(\"window/showMessage not implemented: \" + JSON.stringify(args.toString()))\n        })\n\n        this.subscribeToLanguageServerNotification(\"window/logMessage\", args => {\n            logVerbose(args)\n        })\n\n        this.subscribeToLanguageServerNotification(\"telemetry/event\", args => {\n            logDebug(args)\n        })\n\n        this.handleLanguageServerRequest(\"workspace/configuration\", async req => {\n            Log.warn(\"workspace/configuration not implemented: \" + JSON.stringify(req.toString()))\n            return null\n        })\n\n        this.handleLanguageServerRequest(\"window/showMessageRequest\", async req => {\n            logVerbose(req)\n            return null\n        })\n\n        listenForWorkspaceEdits(this, this._oni)\n    }\n\n    public getCapabilitiesForLanguage(language: string): Promise<IServerCapabilities> {\n        const languageClient = this._getLanguageClient(language)\n\n        if (languageClient) {\n            return Promise.resolve(languageClient.serverCapabilities)\n        } else {\n            return Promise.resolve(null)\n        }\n    }\n\n    public getTokenRegex(language: string): RegExp {\n        const languageSpecificTokenRegex = this._oni.configuration.getValue(\n            `language.${language}.tokenRegex`,\n        ) as RegExp\n\n        if (languageSpecificTokenRegex) {\n            return RegExp(languageSpecificTokenRegex, \"i\")\n        } else {\n            return /[$_a-zA-Z0-9]/i\n        }\n    }\n\n    public getSignatureHelpTriggerCharacters(language: string): string[] {\n        return [\"(\"]\n    }\n\n    public getCompletionTriggerCharacters(language: string): string[] {\n        const languageSpecificTriggerChars = this._oni.configuration.getValue(\n            `language.${language}.completionTriggerCharacters`,\n        ) as string[]\n\n        if (languageSpecificTriggerChars) {\n            return languageSpecificTriggerChars\n        } else {\n            return [\".\"]\n        }\n    }\n\n    public isLanguageServerAvailable(language: string): boolean {\n        return !!this._getLanguageClient(language)\n    }\n\n    public async sendLanguageServerNotification(\n        language: string,\n        filePath: string,\n        protocolMessage: string,\n        protocolPayload: LanguageClientTypes.NotificationValueOrThunk,\n    ): Promise<void> {\n        const languageClient = this._getLanguageClient(language)\n\n        await this._simulateFakeLag()\n\n        if (languageClient) {\n            await languageClient.sendNotification(filePath, protocolMessage, protocolPayload)\n        } else {\n            Log.verbose(\"No supported language\")\n        }\n    }\n\n    public async sendLanguageServerRequest(\n        language: string,\n        filePath: string,\n        protocolMessage: string,\n        protocolPayload: LanguageClientTypes.NotificationValueOrThunk,\n    ): Promise<any> {\n        const languageClient = this._getLanguageClient(language)\n\n        Log.verbose(\n            \"[LANGUAGE] Sending request: \" +\n                protocolMessage +\n                \"|\" +\n                JSON.stringify(protocolPayload),\n        )\n\n        await this._simulateFakeLag()\n\n        if (languageClient) {\n            try {\n                const result = await languageClient.sendRequest(\n                    filePath,\n                    protocolMessage,\n                    protocolPayload,\n                )\n                this._setStatus(protocolMessage, LanguageClientState.Active)\n                return result\n            } catch (ex) {\n                this._setStatus(protocolMessage, LanguageClientState.Error)\n                throw ex\n            }\n        } else {\n            this._setStatus(protocolMessage, LanguageClientState.NotAvailable)\n            return Promise.reject(\"No language server registered\")\n        }\n    }\n\n    // Register a handler for requests incoming from the language server\n    public handleLanguageServerRequest(\n        protocolMessage: string,\n        callback: (args: ILanguageServerNotificationResponse) => Promise<any>,\n    ): void {\n        const currentHandler = this._requestHandlers[protocolMessage]\n\n        if (currentHandler) {\n            return\n        }\n\n        this._requestHandlers[protocolMessage] = callback\n\n        const languageClients = Object.values(this._languageServerInfo)\n        languageClients.forEach(ls => {\n            ls.handleRequest(protocolMessage, callback)\n        })\n    }\n\n    public subscribeToLanguageServerNotification(\n        protocolMessage: string,\n        callback: (args: ILanguageServerNotificationResponse) => void,\n    ): IDisposable {\n        const currentSubscription = this._notificationSubscriptions[protocolMessage]\n\n        if (!currentSubscription) {\n            const evt = new Event<any>()\n            this._notificationSubscriptions[protocolMessage] = evt\n\n            const languageClients = Object.values(this._languageServerInfo)\n            languageClients.forEach(ls => {\n                ls.subscribe(protocolMessage, evt)\n            })\n\n            return evt.subscribe(args => callback(args))\n        } else {\n            return currentSubscription.subscribe(args => callback(args))\n        }\n    }\n\n    public unwrapFileUriPath(fileUri: string): string {\n        return Helpers.unwrapFileUriPath(fileUri)\n    }\n\n    public wrapPathInFileUri(filePath: string): string {\n        return Helpers.wrapPathInFileUri(filePath)\n    }\n\n    public registerLanguageClient(language: string, languageClient: ILanguageClient): any {\n        if (this._languageServerInfo[language]) {\n            Log.error(\"Duplicate language server registered for: \" + language)\n            return\n        }\n\n        Object.keys(this._notificationSubscriptions).forEach(notification => {\n            languageClient.subscribe(notification, this._notificationSubscriptions[notification])\n        })\n\n        Object.keys(this._requestHandlers).forEach(request => {\n            languageClient.handleRequest(request, this._requestHandlers[request])\n        })\n\n        this._languageServerInfo[language] = languageClient\n\n        // If there is already a buffer open matching this language,\n        // we should send a buffer open event\n        if (\n            this._oni.editors.activeEditor.activeBuffer &&\n            this._oni.editors.activeEditor.activeBuffer.language === language\n        ) {\n            this._onBufferEnter()\n        }\n    }\n\n    private async _onBufferEnter(): Promise<void> {\n        if (!this._oni.editors.activeEditor.activeBuffer) {\n            Log.warn(\"[LanguageManager] No active buffer on buffer enter\")\n            return\n        }\n\n        const buffer = this._oni.editors.activeEditor.activeBuffer\n        const { language, filePath } = buffer\n\n        if (!language && filePath) {\n            const pluginManager = this._oni.plugins as PluginManager // TODO: Refactor API\n            const languages = pluginManager.getAllContributionsOfType<\n                Capabilities.ILanguageContribution\n            >(contributes => contributes.languages)\n            const extension = path.extname(filePath)\n            const matchingLanguages = languages.filter(\n                l => l.extensions.indexOf(extension) && extension && extension.length > 0,\n            )\n            if (matchingLanguages.length > 0) {\n                Log.info(\n                    `[LanguageManager::_onBufferEnter] Setting language for file ${filePath} to ${\n                        matchingLanguages[0].id\n                    }`,\n                )\n                await (buffer as any).setLanguage(matchingLanguages[0].id)\n            }\n        }\n\n        if (language) {\n            this._languageClientStatusBar.show(language)\n\n            if (this._hasLanguageClient(language)) {\n                this._languageClientStatusBar.setStatus(LanguageClientState.Initializing)\n            } else {\n                this._languageClientStatusBar.setStatus(LanguageClientState.NotAvailable)\n            }\n        }\n\n        if (\n            buffer.lineCount >\n            this._oni.configuration.getValue(\"editor.maxLinesForLanguageServices\")\n        ) {\n            this._languageClientStatusBar.setStatus(LanguageClientState.NotAvailable)\n            Log.info(\n                \"[LanguageManager] Not sending 'didOpen' because file line count exceeds limit.\",\n            )\n            return\n        }\n\n        await this.sendLanguageServerNotification(\n            language,\n            filePath,\n            \"textDocument/didOpen\",\n            async () => {\n                this._currentTrackedFile = filePath\n                const lines = await this._oni.editors.activeEditor.activeBuffer.getLines()\n                const text = lines.join(os.EOL)\n                const version = this._oni.editors.activeEditor.activeBuffer.version\n                this._languageClientStatusBar.setStatus(LanguageClientState.Active)\n                return Helpers.pathToTextDocumentItemParams(filePath, language, text, version)\n            },\n        )\n    }\n\n    private _getLanguageClient(language: string): ILanguageClient {\n        if (!language) {\n            return null\n        }\n\n        // Fix for #882 - handle cases like `javascript.jsx` where there is\n        // some scoping to the filetype / language name\n        const normalizedLanguage = language.split(\".\")[0]\n\n        return this._languageServerInfo[normalizedLanguage]\n    }\n\n    private _hasLanguageClient(language: string): boolean {\n        return !!this._languageServerInfo[language]\n    }\n\n    private _setStatus(protocolMessage: string, status: LanguageClientState): void {\n        switch (protocolMessage) {\n            case \"textDocument/didOpen\":\n            case \"textDocument/didChange\":\n                this._languageClientStatusBar.setStatus(status)\n                break\n            default:\n                break\n        }\n    }\n\n    private async _simulateFakeLag(): Promise<void> {\n        const delay = this._oni.configuration.getValue(\"debug.fakeLag.languageServer\") as number\n        if (!delay) {\n            return\n        } else {\n            await Utility.delay(delay)\n        }\n    }\n}\n\nconst logVerbose = (args: any) => {\n    if (Log.isVerboseLoggingEnabled()) {\n        Log.verbose(\"[Language Manager] \" + JSON.stringify(args))\n    }\n}\n\nconst logDebug = (args: any) => {\n    if (Log.isDebugLoggingEnabled()) {\n        Log.debug(\"[Language Manager] \" + JSON.stringify(args))\n    }\n}\n\nlet _languageManager: LanguageManager = null\n\nexport const activate = (oni: Oni.Plugin.Api): void => {\n    _languageManager = new LanguageManager(oni)\n}\n\nexport const getInstance = (): LanguageManager => {\n    return _languageManager\n}\n"
  },
  {
    "path": "browser/src/Services/Language/LanguageStore.ts",
    "content": "/**\n * LanguageStore.ts\n *\n * Manages state for UI-facing elements, like\n * hover & definition\n */\n\nimport \"rxjs/add/observable/of\"\nimport { Observable } from \"rxjs/Observable\"\n\nimport { combineReducers, Reducer, Store } from \"redux\"\nimport { combineEpics, createEpicMiddleware, Epic } from \"redux-observable\"\n\nimport { createStore as oniCreateStore } from \"./../../Redux\"\n\nimport { Configuration } from \"./../Configuration\"\n\nimport { IDefinitionRequestor, IDefinitionResult } from \"./DefinitionRequestor\"\nimport { IHoverRequestor, IHoverResult } from \"./HoverRequestor\"\n\nexport interface ILocation {\n    filePath: string\n    language: string\n    line: number\n    column: number\n}\n\nexport interface ILocationBasedResult<T> extends ILocation {\n    result: T | null\n}\n\nexport const DefaultLocationBasedResult: ILocationBasedResult<any> = {\n    filePath: null,\n    language: null,\n    line: -1,\n    column: -1,\n    result: null,\n}\n\nexport interface IActiveBufferState {\n    filePath: string\n    language: string\n}\n\nexport const DefaultActiveBuffer: IActiveBufferState = {\n    filePath: null,\n    language: null,\n}\n\nexport interface ICursorPositionState {\n    line: number\n    column: number\n}\n\nexport const DefaultCursorPosition: ICursorPositionState = {\n    line: -1,\n    column: -1,\n}\n\nexport type HoverResult = ILocationBasedResult<IHoverResult>\nexport type DefinitionResult = ILocationBasedResult<IDefinitionResult>\n\nexport interface ILanguageState {\n    mode: string\n    activeBuffer: IActiveBufferState\n    cursor: ICursorPositionState\n    hoverResult: HoverResult\n    definitionResult: DefinitionResult\n}\n\nexport const DefaultLanguageState: ILanguageState = {\n    mode: \"\",\n    activeBuffer: DefaultActiveBuffer,\n    cursor: DefaultCursorPosition,\n    hoverResult: DefaultLocationBasedResult,\n    definitionResult: DefaultLocationBasedResult,\n}\n\nexport type LanguageAction =\n    | {\n          type: \"MODE_CHANGED\"\n          mode: string\n      }\n    | {\n          type: \"CURSOR_MOVED\"\n          line: number\n          column: number\n      }\n    | {\n          type: \"BUFFER_ENTER\"\n          filePath: string\n          language: string\n      }\n    | {\n          type: \"HOVER_QUERY\"\n          location: ILocation\n      }\n    | {\n          type: \"DEFINITION_QUERY\"\n          location: ILocation\n      }\n    | {\n          type: \"HOVER_QUERY_RESULT\"\n          result: ILocationBasedResult<IHoverResult>\n      }\n    | {\n          type: \"DEFINITION_QUERY_RESULT\"\n          result: ILocationBasedResult<IDefinitionResult>\n      }\n\nexport const modeReducer: Reducer<string> = (state: string = null, action: LanguageAction) => {\n    switch (action.type) {\n        case \"MODE_CHANGED\":\n            return action.mode\n        default:\n            return state\n    }\n}\n\nexport const activeBufferReducer: Reducer<IActiveBufferState> = (\n    state: IActiveBufferState = DefaultActiveBuffer,\n    action: LanguageAction,\n) => {\n    switch (action.type) {\n        case \"BUFFER_ENTER\":\n            return {\n                ...state,\n                filePath: action.filePath,\n                language: action.language,\n            }\n        default:\n            return state\n    }\n}\n\nexport const cursorMovedReducer: Reducer<ICursorPositionState> = (\n    state: ICursorPositionState = DefaultCursorPosition,\n    action: LanguageAction,\n) => {\n    switch (action.type) {\n        case \"CURSOR_MOVED\":\n            return {\n                ...state,\n                line: action.line,\n                column: action.column,\n            }\n        default:\n            return state\n    }\n}\n\nexport const hoverResultReducer: Reducer<HoverResult> = (\n    state: HoverResult = DefaultLocationBasedResult,\n    action: LanguageAction,\n) => {\n    switch (action.type) {\n        case \"HOVER_QUERY_RESULT\":\n            return action.result\n        case \"CURSOR_MOVED\":\n        case \"BUFFER_ENTER\":\n        case \"MODE_CHANGED\":\n            return DefaultLocationBasedResult\n        default:\n            return state\n    }\n}\n\nexport const definitionResultReducer: Reducer<DefinitionResult> = (\n    state: DefinitionResult = DefaultLocationBasedResult,\n    action: LanguageAction,\n) => {\n    switch (action.type) {\n        case \"DEFINITION_QUERY_RESULT\":\n            return action.result\n        case \"CURSOR_MOVED\":\n        case \"BUFFER_ENTER\":\n        case \"MODE_CHANGED\":\n            return DefaultLocationBasedResult\n        default:\n            return state\n    }\n}\n\nexport const languageStateReducer = combineReducers<ILanguageState>({\n    mode: modeReducer,\n    activeBuffer: activeBufferReducer,\n    cursor: cursorMovedReducer,\n    definitionResult: definitionResultReducer,\n    hoverResult: hoverResultReducer,\n})\n\nexport const createStore = (\n    configuration: Configuration,\n    hoverRequestor: IHoverRequestor,\n    definitionRequestor: IDefinitionRequestor,\n): Store<ILanguageState> => {\n    const epicMiddleware = createEpicMiddleware(\n        combineEpics(\n            queryForDefinitionEpic(configuration),\n            queryForHoverEpic(configuration),\n            queryDefinitionEpic(definitionRequestor),\n            queryHoverEpic(hoverRequestor),\n        ),\n    )\n\n    return oniCreateStore<ILanguageState>(\"LANGUAGE\", languageStateReducer, DefaultLanguageState, [\n        epicMiddleware,\n    ])\n}\nexport const queryForHoverEpic = (\n    configuration: Configuration,\n): Epic<LanguageAction, ILanguageState> => (action$, store) =>\n    action$\n        .ofType(\"CURSOR_MOVED\")\n        .filter(\n            () =>\n                store.getState().mode === \"normal\" &&\n                configuration.getValue(\"editor.quickInfo.enabled\"),\n        )\n        .debounceTime(configuration.getValue(\"editor.quickInfo.delay\"))\n        .filter(() => store.getState().mode === \"normal\")\n        .map((action: LanguageAction) => {\n            const currentState = store.getState()\n            const filePath = currentState.activeBuffer.filePath\n            const language = currentState.activeBuffer.language\n            const line = currentState.cursor.line\n            const column = currentState.cursor.column\n\n            const location = {\n                filePath,\n                language,\n                line,\n                column,\n            }\n\n            return {\n                type: \"HOVER_QUERY\",\n                location,\n            } as LanguageAction\n        })\n\nexport const queryForDefinitionEpic = (\n    configuration: Configuration,\n): Epic<LanguageAction, ILanguageState> => (action$, store) =>\n    action$\n        .ofType(\"CURSOR_MOVED\")\n        .debounceTime(configuration.getValue(\"editor.quickInfo.delay\"))\n        .filter(() => store.getState().mode === \"normal\")\n        .filter(\n            () =>\n                store.getState().mode === \"normal\" &&\n                configuration.getValue(\"editor.definition.enabled\"),\n        )\n        .map((action: LanguageAction) => {\n            const currentState = store.getState()\n            const filePath = currentState.activeBuffer.filePath\n            const language = currentState.activeBuffer.language\n            const line = currentState.cursor.line\n            const column = currentState.cursor.column\n\n            const location = {\n                filePath,\n                language,\n                line,\n                column,\n            }\n\n            return {\n                type: \"DEFINITION_QUERY\",\n                location,\n            } as LanguageAction\n        })\n\nexport const NullAction = { type: null } as LanguageAction\n\nexport const doesLocationBasedResultMatchCursorPosition = (\n    result: ILocationBasedResult<any>,\n    state: ILanguageState,\n) => {\n    return (\n        result.filePath === state.activeBuffer.filePath &&\n        result.line === state.cursor.line &&\n        result.column === state.cursor.column &&\n        state.mode === \"normal\"\n    )\n}\n\nexport const queryDefinitionEpic = (\n    definitionRequestor: IDefinitionRequestor,\n): Epic<LanguageAction, ILanguageState> => (action$, store) =>\n    action$\n        .ofType(\"DEFINITION_QUERY\")\n        .switchMap(() => {\n            const state = store.getState()\n\n            const { filePath, language } = state.activeBuffer\n            const { line, column } = state.cursor\n\n            return Observable.defer(async () => {\n                const result = await definitionRequestor.getDefinition(\n                    language,\n                    filePath,\n                    line,\n                    column,\n                )\n                return {\n                    type: \"DEFINITION_QUERY_RESULT\",\n                    result: {\n                        filePath,\n                        language,\n                        line,\n                        column,\n                        result,\n                    },\n                } as LanguageAction\n            })\n        })\n        .filter(action => {\n            if (action.type !== \"DEFINITION_QUERY_RESULT\") {\n                return false\n            }\n\n            return doesLocationBasedResultMatchCursorPosition(action.result, store.getState())\n        })\n\nexport const queryHoverEpic = (\n    hoverRequestor: IHoverRequestor,\n): Epic<LanguageAction, ILanguageState> => (action$, store) =>\n    action$\n        .ofType(\"HOVER_QUERY\")\n        .switchMap(() => {\n            const state = store.getState()\n\n            const { filePath, language } = state.activeBuffer\n            const { line, column } = state.cursor\n\n            return Observable.defer(async () => {\n                const result = await hoverRequestor.getHover(language, filePath, line, column)\n                return {\n                    type: \"HOVER_QUERY_RESULT\",\n                    result: {\n                        filePath,\n                        language,\n                        line,\n                        column,\n                        result,\n                    },\n                } as LanguageAction\n            })\n        })\n        .filter(action => {\n            if (action.type !== \"HOVER_QUERY_RESULT\") {\n                return false\n            }\n\n            return doesLocationBasedResultMatchCursorPosition(action.result, store.getState())\n        })\n"
  },
  {
    "path": "browser/src/Services/Language/PromiseQueue.ts",
    "content": "import * as Log from \"oni-core-logging\"\n\nexport class PromiseQueue {\n    private _currentPromise: Promise<any> = Promise.resolve(null)\n\n    public enqueuePromise<T>(\n        functionThatReturnsPromiseOrThenable: () => Promise<T> | Thenable<T>,\n        requireConnection: boolean = true,\n    ): Promise<T> {\n        const promiseExecutor = () => {\n            return functionThatReturnsPromiseOrThenable()\n        }\n\n        const newPromise = this._currentPromise.then(\n            () => promiseExecutor(),\n            err => {\n                Log.error(err)\n                return promiseExecutor()\n            },\n        )\n\n        this._currentPromise = newPromise\n        return newPromise\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/RenameView.tsx",
    "content": "/**\n * RenameView.tsx\n *\n * Contents of the Rename tooltip\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nimport { TextInputView } from \"./../../UI/components/LightweightText\"\n\nexport interface IRenameViewProps {\n    tokenName: string\n    onComplete: (val: string) => void\n    onCancel: () => void\n}\n\nconst ToolTipWrapper = styled.div`\n    background-color: ${props => props.theme[\"toolTip.background\"]};\n    color: ${props => props.theme[\"toolTip.foreground\"]};\n\n    input {\n        background-color: ${props => props.theme[\"toolTip.background\"]};\n        color: ${props => props.theme[\"toolTip.foreground\"]};\n    }\n`\n\nexport class RenameView extends React.PureComponent<IRenameViewProps, {}> {\n    public render(): JSX.Element {\n        return (\n            <ToolTipWrapper className=\"rename\">\n                <TextInputView {...this.props} defaultValue={this.props.tokenName} />\n            </ToolTipWrapper>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Language/ServerCapabilities.ts",
    "content": "/*/\n * ServerCapibilities.ts\n */\n\n// Copied from:\n// https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md\n\n/**\n * Defines how the host (editor) should sync document changes to the language server.\n */\nexport namespace TextDocumentSyncKind {\n    /**\n     * Documents should not be synced at all.\n     */\n    export const None = 0\n\n    /**\n     * Documents are synced by always sending the full content\n     * of the document.\n     */\n    export const Full = 1\n\n    /**\n     * Documents are synced by sending the full content on open.\n     * After that only incremental updates to the document are\n     * send.\n     */\n    export const Incremental = 2\n}\n\n/**\n * Completion options.\n */\nexport interface CompletionOptions {\n    /**\n     * The server provides support to resolve additional\n     * information for a completion item.\n     */\n    resolveProvider?: boolean\n\n    /**\n     * The characters that trigger completion automatically.\n     */\n    triggerCharacters?: string[]\n}\n/**\n * Signature help options.\n */\nexport interface SignatureHelpOptions {\n    /**\n     * The characters that trigger signature help\n     * automatically.\n     */\n    triggerCharacters?: string[]\n}\n\n/**\n * Code Lens options.\n */\nexport interface CodeLensOptions {\n    /**\n     * Code lens has a resolve provider as well.\n     */\n    resolveProvider?: boolean\n}\n\n/**\n * Format document on type options\n */\nexport interface DocumentOnTypeFormattingOptions {\n    /**\n     * A character on which formatting should be triggered, like `}`.\n     */\n    firstTriggerCharacter: string\n\n    /**\n     * More trigger characters.\n     */\n    moreTriggerCharacter?: string[]\n}\n\n/**\n * Document link options\n */\nexport interface DocumentLinkOptions {\n    /**\n     * Document links have a resolve provider as well.\n     */\n    resolveProvider?: boolean\n}\n\n/**\n * Execute command options.\n */\nexport interface ExecuteCommandOptions {\n    /**\n     * The commands to be executed on the server\n     */\n    commands: string[]\n}\n\n/**\n * Save options.\n */\nexport interface SaveOptions {\n    /**\n     * The client is supposed to include the content on save.\n     */\n    includeText?: boolean\n}\n\nexport interface TextDocumentSyncOptions {\n    /**\n     * Open and close notifications are sent to the server.\n     */\n    openClose?: boolean\n    /**\n     * Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full\n     * and TextDocumentSyncKindIncremental.\n     */\n    change?: number\n    /**\n     * Will save notifications are sent to the server.\n     */\n    willSave?: boolean\n    /**\n     * Will save wait until requests are sent to the server.\n     */\n    willSaveWaitUntil?: boolean\n    /**\n     * Save notifications are sent to the server.\n     */\n    save?: SaveOptions\n}\n\nexport interface IServerCapabilities {\n    /**\n     * Defines how text documents are synced. Is either a detailed structure defining each notification or\n     * for backwards compatibility the TextDocumentSyncKind number.\n     */\n    textDocumentSync?: TextDocumentSyncOptions | number\n    /**\n     * The server provides hover support.\n     */\n    hoverProvider?: boolean\n    /**\n     * The server provides completion support.\n     */\n    completionProvider?: CompletionOptions\n    /**\n     * The server provides signature help support.\n     */\n    signatureHelpProvider?: SignatureHelpOptions\n    /**\n     * The server provides goto definition support.\n     */\n    definitionProvider?: boolean\n    /**\n     * The server provides find references support.\n     */\n    referencesProvider?: boolean\n    /**\n     * The server provides document highlight support.\n     */\n    documentHighlightProvider?: boolean\n    /**\n     * The server provides document symbol support.\n     */\n    documentSymbolProvider?: boolean\n    /**\n     * The server provides workspace symbol support.\n     */\n    workspaceSymbolProvider?: boolean\n    /**\n     * The server provides code actions.\n     */\n    codeActionProvider?: boolean\n    /**\n     * The server provides code lens.\n     */\n    codeLensProvider?: CodeLensOptions\n    /**\n     * The server provides document formatting.\n     */\n    documentFormattingProvider?: boolean\n    /**\n     * The server provides document range formatting.\n     */\n    documentRangeFormattingProvider?: boolean\n    /**\n     * The server provides document formatting on typing.\n     */\n    documentOnTypeFormattingProvider?: DocumentOnTypeFormattingOptions\n    /**\n     * The server provides rename support.\n     */\n    renameProvider?: boolean\n    /**\n     * The server provides document link support.\n     */\n    documentLinkProvider?: DocumentLinkOptions\n    /**\n     * The server provides execute command support.\n     */\n    executeCommandProvider?: ExecuteCommandOptions\n    /**\n     * Experimental server capabilities.\n     */\n    experimental?: any\n}\n"
  },
  {
    "path": "browser/src/Services/Language/SignatureHelp.ts",
    "content": "/**\n * SignatureHelp.ts\n *\n */\n\nimport { Observable } from \"rxjs/Observable\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { IToolTipsProvider } from \"./../../Editor/NeovimEditor/ToolTipsProvider\"\nimport { editorManager } from \"./../EditorManager\"\n\nimport { ILatestCursorAndBufferInfo } from \"./addInsertModeLanguageFunctionality\"\nimport * as LanguageManager from \"./LanguageManager\"\nimport * as SignatureHelp from \"./SignatureHelpView\"\n\nexport const initUI = (\n    latestCursorAndBufferInfo$: Observable<ILatestCursorAndBufferInfo>,\n    modeChanged$: Observable<Oni.Vim.Mode>,\n    onScroll$: Observable<Oni.EditorBufferScrolledEventArgs>,\n    toolTips: IToolTipsProvider,\n) => {\n    const signatureHelpToolTipName = \"signature-help-tool-tip\"\n\n    onScroll$.subscribe(_ => toolTips.hideToolTip(signatureHelpToolTipName))\n    // Show signature help as the cursor moves\n    latestCursorAndBufferInfo$\n        .flatMap(val =>\n            showSignatureHelp(val.language, val.filePath, val.cursorLine, val.cursorColumn),\n        )\n        .subscribe(result => {\n            if (result) {\n                toolTips.showToolTip(signatureHelpToolTipName, SignatureHelp.render(result), {\n                    position: null,\n                    openDirection: 1,\n                    padding: \"0px\",\n                })\n            } else {\n                toolTips.hideToolTip(signatureHelpToolTipName)\n            }\n        })\n\n    // Hide signature help when we leave insert mode\n    modeChanged$.subscribe(newMode => {\n        if (newMode !== \"insert\") {\n            toolTips.hideToolTip(signatureHelpToolTipName)\n        }\n    })\n}\n\nexport const showSignatureHelp = async (\n    language: string,\n    filePath: string,\n    line: number,\n    column: number,\n): Promise<types.SignatureHelp> => {\n    const languageManager = LanguageManager.getInstance()\n    if (languageManager.isLanguageServerAvailable(language)) {\n        const buffer = editorManager.activeEditor.activeBuffer\n        const currentLine = await buffer.getLines(line, line + 1)\n\n        const requestColumn = getSignatureHelpTriggerColumn(currentLine[0], column, [\"(\"])\n\n        if (requestColumn < 0) {\n            return null\n        }\n\n        const args = {\n            textDocument: {\n                uri: Helpers.wrapPathInFileUri(filePath),\n            },\n            position: {\n                line,\n                character: column,\n            },\n        }\n\n        let result: types.SignatureHelp = null\n        try {\n            result = await languageManager.sendLanguageServerRequest(\n                language,\n                filePath,\n                \"textDocument/signatureHelp\",\n                args,\n            )\n        } catch (ex) {\n            Log.debug(ex)\n        }\n\n        return result\n    } else {\n        return null\n    }\n}\n\n// TODO: `getSignatureHelpTriggerColumn` rename to `getNearestTriggerCharacter`\nexport const getSignatureHelpTriggerColumn = (\n    line: string,\n    character: number,\n    triggerCharacters: string[],\n): number => {\n    let idx = character\n    while (idx >= 0) {\n        if (line[idx] === triggerCharacters[0]) {\n            break\n        }\n\n        idx--\n    }\n\n    return idx\n}\n"
  },
  {
    "path": "browser/src/Services/Language/SignatureHelpView.tsx",
    "content": "import * as React from \"react\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { getDocumentationText } from \"../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\nimport {\n    QuickInfoDocumentation,\n    QuickInfoElement,\n    QuickInfoWrapper,\n    Title,\n} from \"./../../UI/components/QuickInfo\"\nimport { SelectedText, Text } from \"./../../UI/components/Text\"\n\nexport const getElementsFromType = (signatureHelp: types.SignatureHelp): JSX.Element => {\n    const elements = []\n\n    const currentItem = signatureHelp.signatures[signatureHelp.activeSignature]\n\n    if (!currentItem || !currentItem.label || !currentItem.parameters) {\n        return null\n    }\n\n    const label = currentItem.label\n    const parameters = currentItem.parameters\n\n    let remainingSignatureString = label\n\n    let keyIndex = 0\n    for (let i = 0; i < parameters.length; i++) {\n        const parameterLabel = parameters[i].label\n        const parameterIndex = remainingSignatureString.indexOf(parameterLabel)\n\n        if (parameterIndex === -1) {\n            continue\n        }\n\n        keyIndex++\n        const nonArgumentText = remainingSignatureString.substring(0, parameterIndex)\n        elements.push(<Text text={nonArgumentText} key={keyIndex.toString()} />)\n\n        const argumentText = remainingSignatureString.substring(\n            parameterIndex,\n            parameterIndex + parameterLabel.length,\n        )\n\n        keyIndex++\n        if (i === signatureHelp.activeParameter) {\n            elements.push(<SelectedText text={argumentText} key={keyIndex.toString()} />)\n        } else {\n            elements.push(<Text text={argumentText} key={keyIndex.toString()} />)\n        }\n\n        remainingSignatureString = remainingSignatureString.substring(\n            parameterIndex + parameterLabel.length,\n            remainingSignatureString.length,\n        )\n    }\n\n    elements.push(<Text key={remainingSignatureString} text={remainingSignatureString} />)\n\n    const selectedIndex = Math.min(currentItem.parameters.length, signatureHelp.activeParameter)\n    const selectedArgument = currentItem.parameters[selectedIndex]\n\n    return (\n        <React.Fragment>\n            <Title padding=\"0.5rem\" key={\"signatureHelp.title\"}>\n                {elements}\n            </Title>\n            {!!(selectedArgument && selectedArgument.documentation) && (\n                <QuickInfoDocumentation\n                    text={getDocumentationText(selectedArgument.documentation)}\n                />\n            )}\n        </React.Fragment>\n    )\n}\n\nexport const SignatureHelpView = (props: types.SignatureHelp) => (\n    <QuickInfoWrapper>\n        <QuickInfoElement>{getElementsFromType(props)}</QuickInfoElement>\n    </QuickInfoWrapper>\n)\n\nexport const render = (signatureHelp: types.SignatureHelp) => (\n    <SignatureHelpView {...signatureHelp} />\n)\n"
  },
  {
    "path": "browser/src/Services/Language/Workspace.ts",
    "content": "/**\n * Workspace.ts\n *\n * Handles workspace/ messages\n */\n\nimport * as Oni from \"oni-api\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { LanguageManager } from \"./LanguageManager\"\n\nexport const listenForWorkspaceEdits = (languageManager: LanguageManager, oni: Oni.Plugin.Api) => {\n    const workspace = oni.workspace\n    languageManager.handleLanguageServerRequest(\"workspace/applyEdit\", async (args: any) => {\n        const payload: types.WorkspaceEdit = args.payload.edit.changes\n        await workspace.applyEdits(payload)\n        return {\n            applied: true,\n        }\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Language/addInsertModeLanguageFunctionality.ts",
    "content": "/**\n * LanguageEditorIntegration\n *\n * Responsible for listening to editor events,\n * and hooking up the language service functionality.\n */\n\nimport \"rxjs/add/observable/never\"\nimport { Observable } from \"rxjs/Observable\"\n\nimport * as Oni from \"oni-api\"\n\nimport { editorManager } from \"./../EditorManager\"\nimport * as SignatureHelp from \"./SignatureHelp\"\n\nimport { IToolTipsProvider } from \"./../../Editor/NeovimEditor/ToolTipsProvider\"\n\nexport interface ILatestCursorAndBufferInfo {\n    filePath: string\n    language: string\n    cursorLine: number\n    contents: string\n    cursorColumn: number\n}\n\nexport const addInsertModeLanguageFunctionality = (\n    cursorMoved$: Observable<Oni.Cursor>,\n    modeChanged$: Observable<Oni.Vim.Mode>,\n    onScroll$: Observable<Oni.EditorBufferScrolledEventArgs>,\n    toolTips: IToolTipsProvider,\n) => {\n    const latestCursorAndBufferInfo$: Observable<\n        ILatestCursorAndBufferInfo\n    > = cursorMoved$.mergeMap(async cursorPos => {\n        const editor = editorManager.activeEditor\n        const buffer = editor.activeBuffer\n\n        const changedLines: string[] = await buffer.getLines(cursorPos.line, cursorPos.line + 1)\n        const changedLine = changedLines[0]\n        return {\n            filePath: buffer.filePath,\n            language: buffer.language,\n            cursorLine: cursorPos.line,\n            contents: changedLine,\n            cursorColumn: cursorPos.column,\n        }\n    })\n\n    SignatureHelp.initUI(latestCursorAndBufferInfo$, modeChanged$, onScroll$, toolTips)\n}\n"
  },
  {
    "path": "browser/src/Services/Language/index.ts",
    "content": "export * from \"./addInsertModeLanguageFunctionality\"\nexport * from \"./CodeAction\"\nexport * from \"./DefinitionRequestor\"\nexport * from \"./Edits\"\nexport * from \"./FindAllReferences\"\nexport * from \"./Formatting\"\nexport * from \"./HoverRequestor\"\nexport * from \"./LanguageClient\"\nexport * from \"./LanguageClientProcess\"\nexport * from \"./LanguageClientTypes\"\nexport * from \"./LanguageConfiguration\"\nexport * from \"./LanguageEditorIntegration\"\nexport * from \"./LanguageManager\"\nexport * from \"./SignatureHelp\"\n"
  },
  {
    "path": "browser/src/Services/Learning/Achievements/AchievementNotificationRenderer.tsx",
    "content": "/**\n * AchievementNotificationRenderer.tsx\n *\n * This renders the achievement 'pop-up' when an achievement goal is met.\n */\n\nimport { Overlay, OverlayManager } from \"./../../Overlay\"\n\nimport * as React from \"react\"\nimport { CSSTransition, TransitionGroup } from \"react-transition-group\"\nimport styled, { keyframes } from \"styled-components\"\n\nimport { boxShadow, withProps } from \"./../../../UI/components/common\"\nimport { FlipCard } from \"./../../../UI/components/FlipCard\"\nimport { Icon, IconSize } from \"./../../../UI/Icon\"\n\nexport class AchievementNotificationRenderer {\n    private _overlay: Overlay\n\n    constructor(private _overlayManager: OverlayManager) {\n        this._overlay = this._overlayManager.createItem()\n        this._overlay.show()\n        this._overlay.setContents(<AchievementsView achievements={[]} />)\n    }\n\n    public showAchievement(achievement: IAchievement): void {\n        window.setTimeout(() => {\n            this._overlay.setContents(<AchievementsView achievements={[achievement]} />)\n        }, 10)\n\n        // TODO: Better handle multiple achievements here\n        window.setTimeout(() => {\n            this._overlay.setContents(<AchievementsView achievements={[]} />)\n        }, 5000)\n    }\n}\n\nconst AchievementsWrapper = styled.div`\n    & .achievements {\n        position: absolute;\n        top: 0px;\n        left: 0px;\n        right: 0px;\n        bottom: 0px;\n\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        justify-content: flex-end;\n    }\n`\n\nconst EnterKeyframes = keyframes`\n    0% { opacity: 0; transform: translateY(32px) rotateX(-30deg);  }\n    100% { opacity: 1; transform: translateY(0px) rotateX(0deg)); }\n`\n\nconst ExitKeyframes = keyframes`\n    0% { opacity: 1; transform: translateY(0px) rotateX(0deg); }\n    100% { opacity: 0; transform: translateY(-32px) rotateX(30deg); }\n`\n\nconst AnimationDuration = \"0.25s\"\n\nconst AchievementWrapper = withProps<{}>(styled.div)`\n    ${boxShadow}\n    display: flex;\n    flex-direction: row;\n    justify-content: center;\n    align-items: center;\n\n    background-color: ${props => props.theme.background};\n    color: ${props => props.theme.foreground};\n\n    border-radius: 3em;\n    padding: 1em 2em;\n    margin: 2em;\n\n    max-width: 1000px;\n\n    &.animate-enter {\n        animation: ${EnterKeyframes};\n        animation-duration: ${AnimationDuration};\n        animation-timing-function: ease-in;\n        animation-fill-mode: forwards;\n    }\n\n    &.animate-exit {\n        animation: ${ExitKeyframes};\n        animation-duration: ${AnimationDuration};\n        animation-timing-function: ease-out;\n        animation-fill-mode: forwards;\n    }\n`\n\nconst FlipCardWrapper = styled.div`\n    width: 48px;\n    height: 48px;\n    margin: 8px;\n    flex: 0 0 auto;\n`\n\nconst AchievementIconWrapper = withProps<{}>(styled.div)`\n    width: 100%;\n    height: 100%;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    background-color: ${props => props.theme[\"highlight.mode.normal.background\"]};\n    border-radius: 8em;\n`\n\nexport interface IAchievement {\n    title: string\n    description: string\n}\n\nexport interface IAchievementsViewProps {\n    achievements: IAchievement[]\n}\n\nexport const AchievementsView = (props: IAchievementsViewProps) => {\n    const achievements = props.achievements.map(a => <AchievementView key={a.title} {...a} />)\n    return (\n        <AchievementsWrapper className={\"stack layer\"}>\n            <TransitionGroup className=\"achievements\" appear={true}>\n                {achievements}\n            </TransitionGroup>\n        </AchievementsWrapper>\n    )\n}\n\nexport interface AchievementViewState {\n    flipCard: boolean\n}\n\nexport class AchievementView extends React.PureComponent<IAchievement, AchievementViewState> {\n    constructor(props: IAchievement) {\n        super(props)\n\n        this.state = {\n            flipCard: false,\n        }\n    }\n\n    public componentDidMount(): void {\n        window.setTimeout(() => {\n            this.setState({ flipCard: true })\n        }, 1000)\n    }\n\n    public render(): JSX.Element {\n        return (\n            <CSSTransition {...this.props} timeout={2500} classNames=\"animate\" appear={true}>\n                <AchievementWrapper className=\"achievement\" key={this.props.title}>\n                    <FlipCardWrapper>\n                        <FlipCard\n                            isFlipped={this.state.flipCard}\n                            front={\n                                <img\n                                    src=\"images/256x256.png\"\n                                    style={{ width: \"100%\", height: \"100%\" }}\n                                />\n                            }\n                            back={\n                                <AchievementIconWrapper>\n                                    <Icon name=\"trophy\" size={IconSize.TwoX} />\n                                </AchievementIconWrapper>\n                            }\n                        />\n                    </FlipCardWrapper>\n                    <div className=\"container vertical full\" style={{ padding: \"0em 1em\" }}>\n                        <div style={{ fontWeight: \"bold\", paddingBottom: \"0.25em\" }}>\n                            Achievement Unlocked\n                        </div>\n                        <div>{this.props.title}</div>\n                    </div>\n                </AchievementWrapper>\n            </CSSTransition>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Achievements/AchievementsBufferLayer.tsx",
    "content": "/**\n * AchievementsBufferLayer.tsx\n *\n * This is an implementation of a buffer layer to show the\n * achievements in a 'trophy-case' style view\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nimport { BufferLayerHeader } from \"./../../../UI/components/BufferLayerHeader\"\nimport { Bold, boxShadow, Fixed, Full, withProps } from \"./../../../UI/components/common\"\nimport { FlipCard } from \"./../../../UI/components/FlipCard\"\nimport { Icon, IconSize } from \"./../../../UI/Icon\"\n\nimport * as Oni from \"oni-api\"\nimport { IDisposable } from \"oni-types\"\n\nimport { AchievementsManager, AchievementWithProgressInfo } from \"./AchievementsManager\"\n\nexport interface ITrophyCaseViewProps {\n    achievements: AchievementsManager\n}\n\nexport interface ITrophyCaseViewState {\n    progressInfo: AchievementWithProgressInfo[]\n}\n\nexport const TrophyCaseViewWrapper = withProps<{}>(styled.div)`\n    background-color: ${props => props.theme[\"editor.background\"]};\n    color: ${props => props.theme[\"editor.foreground\"]};\n    width: 100%;\n    height: 100%;\n    overflow-y: auto;\n    pointer-events: all;\n\n    display: flex;\n    flex-direction: column;\n\n    justify-content: flex-start;\n`\n\nexport const TrophyCaseItemViewWrapper = withProps<{}>(styled.div)`\n    ${boxShadow}\n    background-color: ${props => props.theme.background};\n    margin: 1em;\n    position: relative;\n\n    display: flex;\n    flex-direction: horizontal;\n`\n\nexport const TrophyCaseBackground = styled.div`\n    position: absolute;\n    color: black;\n    opacity: 0.1;\n    width: 100%;\n    height: 100%;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nexport const TrophyItemIcon = styled.div`\n    width: 48px;\n    height: 48px;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    padding: 1em;\n    margin: 0.5em;\n    background-color: rgba(0, 0, 0, 0.2);\n    color: rgba(255, 255, 255, 0.5);\n`\n\nexport const TitleText = styled.div`\n    padding-bottom: 0.25em;\n    font-weight: bold;\n    opacity: 0.9;\n`\n\nexport const DescriptionText = styled.div`\n    font-size: 0.9em;\n`\n\nexport interface ICenteredIconProps {\n    isSuccess?: boolean\n}\n\nexport const CenteredIcon = withProps<ICenteredIconProps>(styled.div)`\n    width: 100%;\n    height: 100%;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    ${p => (p.isSuccess ? \"color: \" + p.theme[\"highlight.mode.insert.background\"] + \";\" : \"\")}\n`\n\nexport const TrophyCaseItemView = (props: {\n    achievementInfo: AchievementWithProgressInfo\n    dependentAchieventName?: string\n}) => {\n    const isLocked = !!props.dependentAchieventName\n\n    const icon = (\n        <FlipCard\n            isFlipped={props.achievementInfo.completed}\n            front={\n                <CenteredIcon>\n                    <Icon name=\"trophy\" size={IconSize.ThreeX} />\n                </CenteredIcon>\n            }\n            back={\n                <CenteredIcon isSuccess={true}>\n                    <Icon name=\"check\" size={IconSize.ThreeX} />\n                </CenteredIcon>\n            }\n        />\n    )\n\n    const lockedIcon = (\n        <CenteredIcon>\n            <Icon name=\"lock\" size={IconSize.ThreeX} />\n        </CenteredIcon>\n    )\n\n    const description = isLocked ? (\n        <span>\n            Complete the <Bold>{props.dependentAchieventName}</Bold> achievement to unlock\n        </span>\n    ) : (\n        props.achievementInfo.achievement.description\n    )\n\n    return (\n        <TrophyCaseItemViewWrapper>\n            <Fixed>\n                <TrophyItemIcon>{isLocked ? lockedIcon : icon}</TrophyItemIcon>\n            </Fixed>\n            <Full\n                style={{\n                    display: \"flex\",\n                    flexDirection: \"column\",\n                    justifyContent: \"center\",\n                    padding: \"1em\",\n                }}\n            >\n                <TitleText>{isLocked ? null : props.achievementInfo.achievement.name}</TitleText>\n                <DescriptionText>{description}</DescriptionText>\n            </Full>\n        </TrophyCaseItemViewWrapper>\n    )\n}\n\nexport class TrophyCaseView extends React.PureComponent<\n    ITrophyCaseViewProps,\n    ITrophyCaseViewState\n> {\n    private _disposables: IDisposable[] = []\n\n    constructor(props: ITrophyCaseViewProps) {\n        super(props)\n\n        this.state = {\n            progressInfo: props.achievements.getAchievements(),\n        }\n    }\n\n    public componentDidMount(): void {\n        this._cleanSubscriptions()\n\n        const s1 = this.props.achievements.onAchievementAccomplished.subscribe(() => {\n            this.setState({\n                progressInfo: this.props.achievements.getAchievements(),\n            })\n        })\n\n        this._disposables = [s1]\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanSubscriptions()\n    }\n\n    public render(): JSX.Element {\n        const items = this.state.progressInfo.map(item => {\n            let dependentAchievementName = null\n            if (item.locked) {\n                const dependentId = item.achievement.dependsOnId\n                const dependentAchievement = this.state.progressInfo.find(\n                    f => f.achievement.uniqueId === dependentId,\n                )\n                if (dependentAchievement) {\n                    dependentAchievementName = dependentAchievement.achievement.name\n                }\n            }\n\n            return (\n                <TrophyCaseItemView\n                    achievementInfo={item}\n                    dependentAchieventName={dependentAchievementName}\n                />\n            )\n        })\n        return (\n            <TrophyCaseViewWrapper>\n                <TrophyCaseBackground>\n                    <Icon name=\"trophy\" size={IconSize.FiveX} style={{ fontSize: \"20em\" }} />\n                </TrophyCaseBackground>\n                <Fixed>\n                    <BufferLayerHeader\n                        title=\"Achievements\"\n                        description=\"Discover new functionality by unlocking achievements\"\n                    />\n                </Fixed>\n                <Full>{items}</Full>\n            </TrophyCaseViewWrapper>\n        )\n    }\n\n    private _cleanSubscriptions(): void {\n        this._disposables.forEach(d => d.dispose())\n        this._disposables = []\n    }\n}\n\nexport class AchievementsBufferLayer implements Oni.BufferLayer {\n    public get id(): string {\n        return \"oni.layer.achievements\"\n    }\n\n    public get friendlyName(): string {\n        return \"Achievements\"\n    }\n\n    constructor(private _achievements: AchievementsManager) {}\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return <TrophyCaseView achievements={this._achievements} />\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Achievements/AchievementsManager.ts",
    "content": "/**\n * AchievementsManager.ts\n *\n * Primary API entry point for the achievements feature\n */\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as Utility from \"./../../../Utility\"\n\nimport { IPersistentStore } from \"./../../../PersistentStore\"\n\nexport interface AchievementDefinition {\n    uniqueId: string\n    name: string\n    description: string\n\n    // An achievement 'id' that this achievement\n    // depends on, before it can be tracked or available\n    dependsOnId?: string\n\n    goals: AchievementGoalDefinition[]\n}\n\nexport interface AchievementGoalDefinition {\n    name: string\n    goalId: string\n    count: number\n}\n\nexport interface AchievementWithProgressInfo {\n    achievement: AchievementDefinition\n    locked?: boolean\n    completed: boolean\n}\n\nexport class AchievementsManager {\n    private _goalState: IPersistedAchievementState\n    private _achievements: { [achievementId: string]: AchievementDefinition } = {}\n    private _trackingGoals: { [goalId: string]: string[] } = {}\n    private _enabled: boolean\n\n    private _currentIdleCallback: number | null = null\n    private _onAchievementAccomplishedEvent = new Event<AchievementDefinition>()\n\n    public get enabled(): boolean {\n        return this._enabled\n    }\n\n    public set enabled(val: boolean) {\n        this._enabled = val\n    }\n\n    public get onAchievementAccomplished(): IEvent<AchievementDefinition> {\n        return this._onAchievementAccomplishedEvent\n    }\n\n    constructor(private _persistentStore: IPersistentStore<IPersistedAchievementState>) {\n        this._enabled = true\n    }\n\n    public notifyGoal(goalId: string): void {\n        if (!this._isInitialized() || !this._enabled) {\n            return\n        }\n\n        const currentGoal = this._goalState.goalCounts[goalId] || 0\n        this._goalState.goalCounts[goalId] = currentGoal + 1\n\n        // Look at all achievements associated with the goal, and check victory conditions\n        const trackingGoals = this._trackingGoals[goalId] || []\n        trackingGoals.forEach((achievementId: string) => {\n            const achievement = this._achievements[achievementId]\n            this._checkVictoryCondition(achievement)\n        })\n\n        this._schedulePersist()\n    }\n\n    public async start(): Promise<void> {\n        this._goalState = await this._persistentStore.get()\n\n        // Once we've loaded, we need to look at all our achievements,\n        // and see if we should start tracking\n        Object.values(this._achievements).forEach(achievement => {\n            this._checkIfShouldTrackAchievement(achievement)\n            this._checkVictoryCondition(achievement)\n        })\n    }\n\n    public getAchievements(): AchievementWithProgressInfo[] {\n        const allAchievements = Object.values(this._achievements)\n\n        return allAchievements.map(achievement => {\n            const isDependentAchievementCompleted =\n                !achievement.dependsOnId ||\n                this._goalState.achievedIds.indexOf(achievement.dependsOnId) >= 0\n            const completed =\n                isDependentAchievementCompleted &&\n                this._goalState.achievedIds.indexOf(achievement.uniqueId) >= 0\n            return {\n                achievement,\n                completed,\n                locked: !isDependentAchievementCompleted,\n            }\n        })\n    }\n\n    public clearAchievements(): void {\n        const clearedState: IPersistedAchievementState = {\n            goalCounts: {},\n            achievedIds: [],\n        }\n\n        this._goalState = clearedState\n        this._persistentStore.set(clearedState)\n    }\n\n    public registerAchievement(definition: AchievementDefinition): void {\n        this._achievements[definition.uniqueId] = definition\n        this._checkIfShouldTrackAchievement(definition)\n        this._checkVictoryCondition(definition)\n    }\n\n    private _isInitialized(): boolean {\n        return !!this._goalState\n    }\n\n    private _checkVictoryCondition(definition: AchievementDefinition): void {\n        if (!this._isInitialized()) {\n            return\n        }\n\n        if (this._hasAchievementBeenAchieved(definition.uniqueId)) {\n            return\n        }\n\n        const areAllGoalsSatisfied = definition.goals.reduce((prev: boolean, goal) => {\n            const hitCount = this._goalState.goalCounts[goal.goalId] || 0\n            return prev && goal.count <= hitCount\n        }, true)\n\n        if (areAllGoalsSatisfied) {\n            this._goalState.achievedIds.push(definition.uniqueId)\n            this._onAchievementAccomplishedEvent.dispatch(definition)\n        }\n    }\n\n    private _hasAchievementBeenAchieved(achievementId: string): boolean {\n        return this._goalState.achievedIds.indexOf(achievementId) >= 0\n    }\n\n    private _checkIfShouldTrackAchievement(definition: AchievementDefinition): void {\n        if (!this._isInitialized()) {\n            return\n        }\n\n        if (this._hasAchievementBeenAchieved(definition.uniqueId)) {\n            // Already been achieved!\n            return\n        }\n\n        // Not achieved, so we'll track all the goalIds\n        definition.goals.forEach(goal => {\n            const currentTrackedItems = this._trackingGoals[goal.goalId] || []\n            this._trackingGoals[goal.goalId] = [...currentTrackedItems, definition.uniqueId]\n        })\n    }\n\n    private _schedulePersist(): void {\n        if (this._currentIdleCallback !== null) {\n            return\n        }\n\n        this._currentIdleCallback = Utility.requestIdleCallback(() => {\n            this._persistentStore.set(this._goalState)\n            this._currentIdleCallback = null\n        })\n    }\n}\n\nexport interface GoalCounts {\n    [goalId: string]: number\n}\n\nexport interface IPersistedAchievementState {\n    goalCounts: GoalCounts\n\n    // Persisted ids of achievements that are already completed\n    // - no need to bother tracking these.\n    achievedIds: string[]\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Achievements/index.tsx",
    "content": "/**\n * Achievements.ts\n *\n * Entry point for the 'achievements' feature\n */\n\nimport { Configuration } from \"./../../Configuration\"\nimport { OverlayManager } from \"./../../Overlay\"\n\nimport { getPersistentStore, IPersistentStore } from \"./../../../PersistentStore\"\n\nimport { CommandManager } from \"./../../CommandManager\"\nimport { EditorManager } from \"./../../EditorManager\"\nimport { SidebarManager } from \"./../../Sidebar\"\n\nexport * from \"./AchievementsManager\"\n\nimport { AchievementNotificationRenderer } from \"./AchievementNotificationRenderer\"\nimport { AchievementsBufferLayer } from \"./AchievementsBufferLayer\"\nimport { AchievementsManager, IPersistedAchievementState } from \"./AchievementsManager\"\n\nlet _achievements: AchievementsManager = null\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n    sidebarManager: SidebarManager,\n    overlays: OverlayManager,\n) => {\n    const achievementsEnabled = configuration.getValue(\"achievements.enabled\")\n\n    const store: IPersistentStore<IPersistedAchievementState> = getPersistentStore(\n        \"oni-achievements\",\n        {\n            goalCounts: {},\n            achievedIds: [],\n        },\n    )\n\n    const manager = new AchievementsManager(store)\n    manager.enabled = achievementsEnabled\n    _achievements = manager\n\n    const renderer = new AchievementNotificationRenderer(overlays)\n\n    manager.onAchievementAccomplished.subscribe(achievement => {\n        renderer.showAchievement({\n            title: achievement.name,\n            description: achievement.description,\n        })\n\n        sidebarManager.setNotification(\"oni.sidebar.learning\")\n    })\n\n    manager.registerAchievement({\n        uniqueId: \"oni.achievement.welcome\",\n        name: \"Welcome to Oni!\",\n        description: \"Launch Oni for the first time\",\n        goals: [\n            {\n                name: \"Launch Oni\",\n                goalId: \"oni.goal.launch\",\n                count: 1,\n            },\n        ],\n    })\n\n    manager.registerAchievement({\n        uniqueId: \"oni.achievement.dedication\",\n        dependsOnId: \"oni.achievement.welcome\",\n        name: \"Dedication\",\n        description: \"Launch Oni 25 times\",\n        goals: [\n            {\n                name: \"Launch Oni\",\n                goalId: \"oni.goal.launch\",\n                count: 25,\n            },\n        ],\n    })\n\n    manager.start().then(() => {\n        manager.notifyGoal(\"oni.goal.launch\")\n    })\n\n    const showAchievements = async () => {\n        const buf = await editorManager.activeEditor.openFile(\"ACHIEVEMENTS.oni\")\n        buf.addLayer(new AchievementsBufferLayer(manager))\n    }\n\n    commandManager.registerCommand({\n        command: \"achievements.show\",\n        name: \"Achievements: Open Trophy Case\",\n        detail: \"Show accomplished and in-progress achievements\",\n        execute: () => showAchievements(),\n    })\n}\n\nexport const getInstance = (): AchievementsManager => {\n    return _achievements\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/LearningPane.tsx",
    "content": "/**\n * LearningPane.tsx\n *\n * UX for rendering the bookmarks experience in the sidebar\n */\n\nimport * as React from \"react\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { CommandManager } from \"./../CommandManager\"\n\nimport { PureComponentWithDisposeTracking } from \"./../../UI/components/PureComponentWithDisposeTracking\"\nimport { SidebarButton } from \"./../../UI/components/SidebarButton\"\nimport { SidebarContainerView, SidebarItemView } from \"./../../UI/components/SidebarItemView\"\nimport { VimNavigator } from \"./../../UI/components/VimNavigator\"\n\nimport { Bold, Center, Container, Fixed, Full } from \"./../../UI/components/common\"\nimport { Icon, IconSize } from \"./../../UI/Icon\"\nimport { SidebarPane } from \"./../Sidebar\"\n\nimport { ITutorialMetadataWithProgress, TutorialManager } from \"./Tutorial/TutorialManager\"\n\nimport { noop } from \"./../../Utility\"\n\nexport class LearningPane implements SidebarPane {\n    private _onEnter = new Event<void>()\n    private _onLeave = new Event<void>()\n\n    constructor(\n        private _tutorialManager: TutorialManager,\n        private _commandManager: CommandManager,\n    ) {}\n\n    public get id(): string {\n        return \"oni.sidebar.learning\"\n    }\n\n    public get title(): string {\n        return \"Learn\"\n    }\n\n    public enter(): void {\n        // this._tutorialManager.startTutorial(null)\n        this._onEnter.dispatch()\n    }\n\n    public leave(): void {\n        this._onLeave.dispatch()\n    }\n\n    public render(): JSX.Element {\n        return (\n            <LearningPaneView\n                onEnter={this._onEnter}\n                onLeave={this._onLeave}\n                tutorialManager={this._tutorialManager}\n                onStartTutorial={id => this._tutorialManager.startTutorial(id)}\n                onOpenAchievements={() => this._commandManager.executeCommand(\"achievements.show\")}\n            />\n        )\n    }\n}\n\nexport interface ILearningPaneViewProps {\n    onEnter: IEvent<void>\n    onLeave: IEvent<void>\n    tutorialManager: TutorialManager\n\n    onStartTutorial: (tutorialId: string) => void\n    onOpenAchievements: () => void\n}\n\nexport interface ILearningPaneViewState {\n    isActive: boolean\n    tutorialInfo: ITutorialMetadataWithProgress[]\n}\n\nimport styled from \"styled-components\"\n\nconst TutorialItemViewIconContainer = styled.div`\n    width: 2em;\n    height: 100%;\n    background-color: rgba(0, 0, 0, 0.1);\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nconst TutorialItemTitleWrapper = styled.div`\n    font-size: 0.9em;\n    margin-left: 0.5em;\n`\n\nconst TutorialResultsWrapper = styled.div`\n    font-size: 0.8em;\n`\n\nexport const TutorialItemView = (props: { info: ITutorialMetadataWithProgress }): JSX.Element => {\n    const isCompleted = !!props.info.completionInfo\n\n    const icon = isCompleted ? <Icon name={\"check\"} /> : <Icon name={\"circle-o\"} />\n\n    // TODO: Refactor this to a 'success' theme color, ie: highlight.success.background\n    const backgroundColor = isCompleted ? \"#5AB379\" : \"rgba(0, 0, 0, 0.1)\"\n    // TODO: Refactor this to a 'success' theme color, ie: highlight.success.foreground\n    const color = isCompleted ? \"white\" : null\n\n    const results = isCompleted ? (\n        <div style={{ margin: \"0.5em\" }}>\n            <TutorialResultsWrapper>\n                <Bold>{(props.info.completionInfo.time / 1000).toFixed(2)}</Bold>s\n            </TutorialResultsWrapper>\n            <TutorialResultsWrapper>\n                <Bold>{props.info.completionInfo.keyPresses}</Bold> keys\n            </TutorialResultsWrapper>\n        </div>\n    ) : (\n        <div style={{ margin: \"0.5em\" }}>--</div>\n    )\n\n    return (\n        <Container direction=\"horizontal\" fullWidth={true} style={{ backgroundColor, color }}>\n            <Fixed style={{ backgroundColor }}>\n                <TutorialItemViewIconContainer>{icon}</TutorialItemViewIconContainer>\n            </Fixed>\n            <Full style={{ margin: \"0.5em\", whiteSpace: \"pre-wrap\" }}>\n                <TutorialItemTitleWrapper>{props.info.tutorialInfo.name}</TutorialItemTitleWrapper>\n            </Full>\n            <Fixed>\n                <Center style={{ flexDirection: \"column\" }}>{results}</Center>\n            </Fixed>\n        </Container>\n    )\n}\n\nexport class LearningPaneView extends PureComponentWithDisposeTracking<\n    ILearningPaneViewProps,\n    ILearningPaneViewState\n> {\n    constructor(props: ILearningPaneViewProps) {\n        super(props)\n\n        this.state = {\n            isActive: false,\n            tutorialInfo: this.props.tutorialManager.getTutorialInfo(),\n        }\n    }\n\n    public componentDidMount(): void {\n        super.componentDidMount()\n\n        this.trackDisposable(this.props.onEnter.subscribe(() => this.setState({ isActive: true })))\n        this.trackDisposable(this.props.onLeave.subscribe(() => this.setState({ isActive: false })))\n        this.trackDisposable(\n            this.props.tutorialManager.onTutorialProgressChangedEvent.subscribe(() => {\n                this.setState({\n                    tutorialInfo: this.props.tutorialManager.getTutorialInfo(),\n                })\n            }),\n        )\n    }\n\n    public render(): JSX.Element {\n        const tutorialIds = this.state.tutorialInfo.map(t => t.tutorialInfo.id)\n        const ids = [\"tutorial_container\", ...tutorialIds, \"trophy_case\"]\n\n        const tutorialItems = (selectedId: string) =>\n            this.state.tutorialInfo.map(t => (\n                <SidebarItemView\n                    key={t.tutorialInfo.id}\n                    indentationLevel={0}\n                    isFocused={selectedId === t.tutorialInfo.id}\n                    text={<TutorialItemView info={t} />}\n                    onClick={() => this._onSelect(t.tutorialInfo.id)}\n                />\n            ))\n\n        const InnerTrophyButton: JSX.Element = (\n            <Container\n                direction=\"horizontal\"\n                style={{ justifyContent: \"center\", alignItems: \"center\" }}\n            >\n                <Fixed>\n                    <Icon name=\"trophy\" size={IconSize.Large} />\n                </Fixed>\n                <Full>\n                    <div\n                        style={{\n                            display: \"flex\",\n                            justifyContent: \"center\",\n                            alignItems: \"center\",\n                            width: \"100%\",\n                            height: \"100%\",\n                        }}\n                    >\n                        <div style={{ paddingLeft: \"8px\" }}>Achievements</div>\n                    </div>\n                </Full>\n            </Container>\n        )\n\n        return (\n            <VimNavigator\n                ids={ids}\n                active={this.state.isActive}\n                onSelected={id => this._onSelect(id)}\n                render={selectedId => {\n                    const items = tutorialItems(selectedId)\n                    return (\n                        <Container\n                            fullHeight={true}\n                            fullWidth={true}\n                            direction=\"vertical\"\n                            style={{\n                                position: \"absolute\",\n                                top: \"0px\",\n                                left: \"0px\",\n                                right: \"0px\",\n                                bottom: \"0px\",\n                            }}\n                        >\n                            <Full style={{ height: \"100%\" }}>\n                                <SidebarContainerView\n                                    indentationLevel={0}\n                                    isFocused={selectedId === \"tutorial_container\"}\n                                    text={\"Tutorials\"}\n                                    isContainer={true}\n                                    isExpanded={true}\n                                    onClick={noop}\n                                >\n                                    {items}\n                                </SidebarContainerView>\n                            </Full>\n                            <Fixed>\n                                <div style={{ marginBottom: \"2em\", marginTop: \"2em\" }}>\n                                    <SidebarButton\n                                        text={InnerTrophyButton}\n                                        focused={selectedId === \"trophy_case\"}\n                                        onClick={() => this._onSelect(\"trophy_case\")}\n                                    />\n                                </div>\n                            </Fixed>\n                        </Container>\n                    )\n                }}\n            />\n        )\n    }\n\n    private _onSelect(selectedId: string) {\n        if (selectedId === \"tutorial_container\") {\n            // TODO: Handle expansion\n        } else if (selectedId === \"trophy_case\") {\n            this.props.onOpenAchievements()\n        } else {\n            this.props.onStartTutorial(selectedId)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/CompletionView.tsx",
    "content": "/**\n * CompletionView.tsx\n *\n * 'Goal' item for the tutorial\n */\n\nimport * as React from \"react\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport { Container, Fixed, withProps } from \"./../../../UI/components/common\"\n// import { FlipCard } from \"./../../../UI/components/FlipCard\"\nimport { Icon, IconSize } from \"./../../../UI/Icon\"\n\nexport interface ICompletionViewProps {\n    time: number\n    keyStrokes: number\n}\n\nconst RotatingKeyFrames = keyframes`\n    0% { transform: rotateY(0deg); }\n    100% { transform: rotateY(360deg); }\n`\n\nconst AppearKeyFrames = keyframes`\n    0% { opacity: 0; }\n    100% { opacity: 1; }\n`\n\nexport interface AppearWithDelayProps {\n    delay: number\n}\n\nconst AppearWithDelay = withProps<AppearWithDelayProps>(styled.div)`\n    animation: ${AppearKeyFrames} 1s linear ${p => p.delay}s forwards;\n    opacity: 0;\n`\n\nconst TrophyIconWrapper = withProps<{}>(styled.div)`\n    background-color: rgb(97, 175, 239);\n    color: white;\n    opacity: 0.1;\n\n    width: 144px;\n    height: 144px;\n    border-radius: 72px;\n\n    animation: ${RotatingKeyFrames} 2s linear infinite;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nconst ResultsWrapper = styled.div`\n    color: white;\n    font-size: 2em;\n\n    height: 100%;\n    flex: 1 1 auto;\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n`\n\nconst Bold = styled.span`\n    font-weight: bold;\n`\n\nconst FooterWrapper = styled.div`\n    padding: 1em;\n`\n\nconst Layer = styled.div`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nexport const CompletionView = (props: ICompletionViewProps): JSX.Element => {\n    return (\n        <Container\n            fullHeight={true}\n            fullWidth={true}\n            direction=\"horizontal\"\n            style={{\n                backgroundColor: \"black\",\n                color: \"white\",\n                justifyContent: \"center\",\n                alignItems: \"center\",\n                overflow: \"hidden\",\n            }}\n        >\n            <Layer>\n                <TrophyIconWrapper>\n                    <Icon name=\"trophy\" size={IconSize.FiveX} />\n                </TrophyIconWrapper>\n            </Layer>\n            <Container\n                fullHeight={true}\n                fullWidth={true}\n                direction=\"vertical\"\n                style={{ justifyContent: \"center\", alignItems: \"center\" }}\n            >\n                <Fixed>\n                    <h1>Level Complete!</h1>\n                </Fixed>\n                <ResultsWrapper>\n                    <AppearWithDelay delay={0.5}>\n                        <Bold>Time:</Bold> {(props.time / 1000).toFixed(2)}s\n                    </AppearWithDelay>\n                    <AppearWithDelay delay={1}>\n                        <Bold>Keystrokes:</Bold> {props.keyStrokes}\n                    </AppearWithDelay>\n                </ResultsWrapper>\n                <Fixed>\n                    <FooterWrapper>\n                        <AppearWithDelay delay={1.5}>\n                            Press ENTER to continue or SPACE to restart\n                        </AppearWithDelay>\n                    </FooterWrapper>\n                </Fixed>\n            </Container>\n        </Container>\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/GameplayBufferLayer.tsx",
    "content": "/**\n * GameplayBufferLayer.tsx\n *\n * The gameplay buffer layer is a buffer layer applied on the\n * _nested_ NeovimEditor - so this actually renders the 'game'\n * UI - any additional adorners that are necessary.\n */\n\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\n\nimport { TutorialGameplayManager } from \"./TutorialGameplayManager\"\n\nexport class GameplayBufferLayer implements Oni.BufferLayer {\n    public get id(): string {\n        return \"oni.layer.gameplay\"\n    }\n\n    public get friendlyName(): string {\n        return \"Gameplay\"\n    }\n\n    constructor(private _tutorialGameplayManager: TutorialGameplayManager) {}\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return (\n            <GameplayBufferLayerView\n                context={context}\n                tutorialGameplay={this._tutorialGameplayManager}\n            />\n        )\n    }\n}\n\nexport interface IGameplayBufferLayerViewProps {\n    tutorialGameplay: TutorialGameplayManager\n    context: Oni.BufferLayerRenderContext\n}\n\nexport interface IGameplayBufferLayerViewState {\n    renderFunction: (context: Oni.BufferLayerRenderContext) => JSX.Element\n    tick: number\n}\n\nexport class GameplayBufferLayerView extends React.PureComponent<\n    IGameplayBufferLayerViewProps,\n    IGameplayBufferLayerViewState\n> {\n    constructor(props: IGameplayBufferLayerViewProps) {\n        super(props)\n\n        this.state = {\n            renderFunction: () => null,\n            tick: 0,\n        }\n    }\n\n    public componentDidMount(): void {\n        this.props.tutorialGameplay.onStateChanged.subscribe(newState => {\n            this.setState({\n                renderFunction: newState.renderFunc,\n            })\n        })\n\n        this.props.tutorialGameplay.onTick.subscribe(() => {\n            this.forceUpdate()\n        })\n    }\n\n    public render(): JSX.Element {\n        if (this.state.renderFunction) {\n            return this.state.renderFunction(this.props.context)\n        }\n\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/GoalView.tsx",
    "content": "/**\n * GoalView.tsx\n *\n * 'Goal' item for the tutorial\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nimport { boxShadow, withProps } from \"./../../../UI/components/common\"\nimport { FlipCard } from \"./../../../UI/components/FlipCard\"\nimport { Icon } from \"./../../../UI/Icon\"\n\nexport interface IGoalViewProps {\n    active: boolean\n    completed: boolean\n    description: string\n    visible: boolean\n}\n\nconst GoalWrapper = withProps<IGoalViewProps>(styled.div)`\n    ${p => (p.active ? boxShadow : \"\")};\n    display: ${p => (p.visible ? \"flex\" : \"none\")};\n    background-color: ${p => p.theme.background};\n    transition: all 0.5s linear;\n\n    justify-content: center;\n    align-items: center;\n    flex-direction: row;\n\n    margin: 1em 0em;\n`\n\nconst IconWrapper = withProps<IGoalViewProps>(styled.div)`\n    display: flex;\n    width: 100%;\n    height: 100%;\n    justify-content: center;\n    align-items: center;\n    background-color: rgba(0, 0, 0, 0.2);\n\n    color: ${p => (p.completed ? p.theme[\"highlight.mode.insert.background\"] : p.theme.foreground)};\n`\n\nexport const GoalView = (props: IGoalViewProps): JSX.Element => {\n    return (\n        <GoalWrapper {...props} key={props.description}>\n            <div style={{ width: \"48px\", height: \"48px\", flex: \"0 0 auto\" }}>\n                <FlipCard\n                    isFlipped={props.completed}\n                    front={\n                        <IconWrapper {...props}>\n                            <Icon name=\"circle\" />\n                        </IconWrapper>\n                    }\n                    back={\n                        <IconWrapper {...props}>\n                            <Icon name=\"check\" />\n                        </IconWrapper>\n                    }\n                />\n            </div>\n            <div style={{ width: \"100%\", flex: \"1 1 auto\", padding: \"1em\" }}>\n                {props.description}\n            </div>\n        </GoalWrapper>\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/ITutorial.ts",
    "content": "/**\n * TutorialManager\n */\n\nimport * as Oni from \"oni-api\"\n\n// import * as types from \"vscode-languageserver-types\"\n\nexport interface ITutorialContext {\n    buffer: Oni.Buffer\n    editor: Oni.Editor\n}\n\nexport interface ITutorialStage {\n    goalName?: string\n    tickFunction: (context: ITutorialContext) => Promise<boolean>\n    render?: (renderContext: Oni.BufferLayerRenderContext) => JSX.Element\n}\n\nexport interface ITutorialMetadata {\n    id: string\n    name: string\n    description: string\n    level: number\n}\n\nexport interface ITutorial {\n    metadata: ITutorialMetadata\n    stages: ITutorialStage[]\n    notes?: JSX.Element[]\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Notes.tsx",
    "content": "/**\n * TutorialBufferLayer.tsx\n *\n * Layer that handles the top-level rendering of the tutorial UI,\n * including the nested `NeovimEditor`, description, goals, etc.\n */\n\nimport * as React from \"react\"\n\n// import * as Oni from \"oni-api\"\n// import { Event, IEvent } from \"oni-types\"\n\nimport styled from \"styled-components\"\n\nimport { Bold, withProps } from \"./../../../UI/components/common\"\nimport { Icon, IconSize } from \"./../../../UI/Icon\"\n\nconst NoteWrapper = styled.div`\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n`\n\nconst KeyWrapper = withProps<{}>(styled.div)`\n    background-color: ${props => props.theme.background};\n    color: ${props => props.theme.foreground};\n    border: 1px solid ${props => props.theme.foreground};\n\n    width: 40px;\n    height: 40px;\n\n    flex: 0 0 auto;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    margin: 1em;\n`\n\nconst DescriptionWrapper = styled.div``\n\nexport const KeyWithDescription = (props: {\n    keyCharacter: string\n    description: JSX.Element\n}): JSX.Element => {\n    return (\n        <NoteWrapper>\n            <KeyWrapper>{props.keyCharacter}</KeyWrapper>\n            <DescriptionWrapper>{props.description}</DescriptionWrapper>\n        </NoteWrapper>\n    )\n}\n\nconst VerticalStackWrapper = styled.div`\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    flex-direction: column;\n`\n\nconst IconWrapper = styled.div``\n\nexport const KeyWithIconAbove = (props: {\n    keyCharacter: string\n    icon: JSX.Element\n}): JSX.Element => {\n    return (\n        <VerticalStackWrapper>\n            <IconWrapper>{props.icon}</IconWrapper>\n            <KeyWrapper>{props.keyCharacter}</KeyWrapper>\n        </VerticalStackWrapper>\n    )\n}\n\nexport const IKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"i\"\n            description={\n                <span>\n                    Enters <Bold>insert</Bold> mode at the cursor position\n                </span>\n            }\n        />\n    )\n}\n\nexport const EscKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"esc\"\n            description={\n                <span>\n                    Goes back to <Bold>normal</Bold> mode\n                </span>\n            }\n        />\n    )\n}\n\nexport const OKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"o\"\n            description={\n                <span>\n                    Enters <Bold>insert</Bold> mode, on a new line\n                </span>\n            }\n        />\n    )\n}\n\nexport const UKey = (): JSX.Element => {\n    return <KeyWithDescription keyCharacter=\"u\" description={<span>Undo a single change</span>} />\n}\n\nexport const RedoKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription keyCharacter=\"Ctrl-r\" description={<span>Redo a single undo</span>} />\n    )\n}\n\nexport const GGKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"gg\"\n            description={<span>Moves the cursor to the TOP of the file.</span>}\n        />\n    )\n}\n\nexport const GKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"G\"\n            description={<span>Moves the cursor to the BOTTOM of the file.</span>}\n        />\n    )\n}\n\nexport const XGKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"#+G\"\n            description={\n                <span>Moves the cursor to line `#`. For example, `10G` moves to line 10.</span>\n            }\n        />\n    )\n}\n\nexport const ZeroKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"0\"\n            description={<span>Moves the cursor to the BEGINNING of the line.</span>}\n        />\n    )\n}\nexport const UnderscoreKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"_\"\n            description={<span>Moves the cursor to the FIRST CHARACTER of the line.</span>}\n        />\n    )\n}\nexport const DollarKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"$\"\n            description={<span>Moves the cursor to the END of the line.</span>}\n        />\n    )\n}\nexport const WordKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"w\"\n            description={<span>Moves the cursor to the BEGINNING of the NEXT word.</span>}\n        />\n    )\n}\nexport const BeginningKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"b\"\n            description={<span>Moves the cursor to the BEGINNING of the PREVIOUS word.</span>}\n        />\n    )\n}\nexport const EndKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"e\"\n            description={<span>Moves the cursor to the END of the NEXT word.</span>}\n        />\n    )\n}\nexport const BigWordKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"W\"\n            description={\n                <span>Moves the cursor to the BEGINNING of the NEXT word by WHITESPACE.</span>\n            }\n        />\n    )\n}\nexport const BigBeginningKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"B\"\n            description={\n                <span>Moves the cursor to the BEGINNING of the PREVIOUS word by WHITESPACE.</span>\n            }\n        />\n    )\n}\nexport const BigEndKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"E\"\n            description={<span>Moves the cursor to the END of the NEXT word by WHITESPACE.</span>}\n        />\n    )\n}\nexport const SlashKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"/\"\n            description={<span>Search for the given string</span>}\n        />\n    )\n}\nexport const QuestionKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"?\"\n            description={<span>Search backwards for the given string</span>}\n        />\n    )\n}\nexport const nKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"n\"\n            description={<span>Move the cursor to the next instance of the matched string</span>}\n        />\n    )\n}\nexport const NKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"N\"\n            description={\n                <span>Move the cursor to the previous instance of the matched string</span>\n            }\n        />\n    )\n}\nexport const DeleteOperatorKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"d\"\n            description={\n                <span>\n                    <Bold>+ motion</Bold>: Deletes text specified by a `motion`\n                </span>\n            }\n        />\n    )\n}\nexport const DeleteLineKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"dd\"\n            description={<span>Deletes the CURRENT line.</span>}\n        />\n    )\n}\nexport const DeleteLineBelowKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"dj\"\n            description={<span>Deletes the CURRENT line and the one BELOW.</span>}\n        />\n    )\n}\nexport const DeleteLineAboveKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"dk\"\n            description={<span>Deletes the CURRENT line and the one ABOVE.</span>}\n        />\n    )\n}\nexport const DeleteWordKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"dw\"\n            description={<span>Delete to the end of the current word.</span>}\n        />\n    )\n}\n\nexport const ChangeOperatorKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"c\"\n            description={\n                <span>\n                    <Bold>+ motion</Bold>: Change text specified by a `motion`\n                </span>\n            }\n        />\n    )\n}\nexport const ChangeWordKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"cw\"\n            description={<span>Delete to the end of the current word and enter Insert mode.</span>}\n        />\n    )\n}\n\nexport const HJKLKeys = (): JSX.Element => {\n    return (\n        <NoteWrapper style={{ margin: \"2em 0em\" }}>\n            <KeyWithIconAbove\n                keyCharacter={\"h\"}\n                icon={<Icon name=\"arrow-left\" size={IconSize.Large} />}\n            />\n            <KeyWithIconAbove\n                keyCharacter={\"j\"}\n                icon={<Icon name=\"arrow-down\" size={IconSize.Large} />}\n            />\n            <KeyWithIconAbove\n                keyCharacter={\"k\"}\n                icon={<Icon name=\"arrow-up\" size={IconSize.Large} />}\n            />\n            <KeyWithIconAbove\n                keyCharacter={\"l\"}\n                icon={<Icon name=\"arrow-right\" size={IconSize.Large} />}\n            />\n        </NoteWrapper>\n    )\n}\n\nexport const YankOperatorKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"y\"\n            description={\n                <span>\n                    <Bold>+ motion</Bold>: Yanks (copies) text specified by a `motion`\n                </span>\n            }\n        />\n    )\n}\nexport const YankWordKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"yw\"\n            description={<span>Yank to the end of the current word.</span>}\n        />\n    )\n}\nexport const YankLineKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription keyCharacter=\"yy\" description={<span>Yanks the CURRENT line.</span>} />\n    )\n}\nexport const pasteKey = (): JSX.Element => {\n    return <KeyWithDescription keyCharacter=\"p\" description={<span>Paste AFTER the cursor</span>} />\n}\nexport const PasteKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription keyCharacter=\"P\" description={<span>Paste BEFORE the cursor</span>} />\n    )\n}\n\nexport const VisualModeKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"v\"\n            description={<span>Move into Visual mode for selecting text</span>}\n        />\n    )\n}\nexport const VisualLineModeKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"V\"\n            description={<span>Move into line-wise Visual mode for selecting lines</span>}\n        />\n    )\n}\n\nexport const Targetckey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"c\"\n            description={<span>Delete AND INSERT between next pair characters</span>}\n        />\n    )\n}\n\nexport const Targetdkey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"d\"\n            description={<span>Delete between next pair characters</span>}\n        />\n    )\n}\n\nexport const Targetikey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"i\"\n            description={<span>Select first character inside of pair characters</span>}\n        />\n    )\n}\n\nexport const Targetakey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"a\"\n            description={<span>Select next pair including the pair characters</span>}\n        />\n    )\n}\n\nexport const TargetIkey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"I\"\n            description={<span>Select contents of pair characters</span>}\n        />\n    )\n}\n\nexport const TargetAkey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"A\"\n            description={<span>Select around the pair characters</span>}\n        />\n    )\n}\n\nexport const Targetnkey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"n\"\n            description={<span>Select the next pair characters</span>}\n        />\n    )\n}\n\nexport const Targetlkey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"l\"\n            description={<span>Select the previous pair characters</span>}\n        />\n    )\n}\n\nexport const fKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"f\"\n            description={\n                <span>\n                    <Bold>+ char</Bold>: Moves cursor to next occurence of [char].\n                </span>\n            }\n        />\n    )\n}\n\nexport const FKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"F\"\n            description={\n                <span>\n                    <Bold>+ char</Bold>: Moves cursor to previous occurence of [char].\n                </span>\n            }\n        />\n    )\n}\n\nexport const tKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"t\"\n            description={\n                <span>\n                    <Bold>+ char</Bold>: Moves cursor to before the next occurence of [char].\n                </span>\n            }\n        />\n    )\n}\n\nexport const TKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"T\"\n            description={\n                <span>\n                    <Bold>+ char</Bold>: Moves cursor to after the previous occurence of [char].\n                </span>\n            }\n        />\n    )\n}\n\nexport const RepeatKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\";\"\n            description={<span>Repeats last f, t, F, or T.</span>}\n        />\n    )\n}\n\nexport const RepeatOppositeKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\",\"\n            description={<span>Repeats last f, t, F, or T in the opposite direction.</span>}\n        />\n    )\n}\n\nexport const innerTextObjectKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"i\"\n            description={<span>Select a Text Object within delimiter characters</span>}\n        />\n    )\n}\n\nexport const aTextObjectKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\"a\"\n            description={<span>Select a Text Object and its delimiter characters</span>}\n        />\n    )\n}\n\nexport const DotKey = (): JSX.Element => {\n    return (\n        <KeyWithDescription\n            keyCharacter=\".\"\n            description={<span>Repeat the last file change made</span>}\n        />\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/CompositeStage.tsx",
    "content": "/**\n * CompositeStage.tsx\n *\n * A stage that combines / composes multiple stages\n */\n\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport const combine = (goalName: string, ...stages: ITutorialStage[]): ITutorialStage => {\n    return new CompositeStage(goalName, stages)\n}\n\nconst ContainerWrapper = styled.div`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n`\n\nexport class CompositeStage implements ITutorialStage {\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(private _goalName: string, private _stages: ITutorialStage[]) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        const promises = this._stages.map(s => s.tickFunction(context))\n\n        const results = await Promise.all(promises)\n\n        return results.reduce((prev, curr) => {\n            return prev && curr\n        }, true)\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return <ContainerWrapper>{this._stages.map(s => s.render(context))}</ContainerWrapper>\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/CorrectLineStage.tsx",
    "content": "/**\n * CorrectLineStage.tsx\n *\n *\n */\n\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport styled, { keyframes } from \"styled-components\"\nimport { withProps } from \"./../../../../UI/components/common\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nconst SpinnerKeyFrames = keyframes`\n    0% {transform: rotateY(0deg); }\n    100% { transform: rotateY(360deg); }\n`\n\nexport interface ArrowProps {\n    color: string\n}\n\nconst TopArrow = withProps<ArrowProps>(styled.div)`\n    animation: ${SpinnerKeyFrames} 2s linear infinite;\n    border-top: 6px solid ${p => p.color};\n    border-left: 3px solid transparent;\n    border-right: 3px solid transparent;\n    border-bottom: 3px solid transparent;\n    opacity: 0.8;\n`\n\nconst BottomArrow = styled.div`\n    animation: ${SpinnerKeyFrames} 2s linear infinite;\n    margin-top: 2px;\n    border-top: 3px solid transparent;\n    border-left: 3px solid transparent;\n    border-right: 3px solid transparent;\n    border-bottom: 6px solid ${p => p.color};\n    opacity: 0.8;\n`\n\nconst getFirstCharacterThatIsDifferent = (line1: string, line2: string): number => {\n    if (!line1 || !line2) {\n        return -1\n    }\n\n    let idx = 0\n\n    while (idx < line1.length && idx < line2.length) {\n        if (line1[idx] !== line2[idx]) {\n            return idx\n        }\n\n        idx++\n    }\n    return idx\n}\n\nexport class CorrectLineStage implements ITutorialStage {\n    private _diffPosition: number\n\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(\n        private _goalName: string,\n        private _line: number,\n        private _expectedText: string,\n        private _color: string = \"red\",\n        private _minimumLine?: string,\n    ) {\n        if (!this._minimumLine) {\n            this._minimumLine = this._expectedText\n        }\n    }\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        const [currentLine] = await (context.buffer as any).getLines(this._line, this._line + 1)\n        const diffPosition = getFirstCharacterThatIsDifferent(currentLine, this._expectedText)\n        this._diffPosition = diffPosition\n\n        if (currentLine.startsWith(this._minimumLine)) {\n            return true\n        }\n\n        return false\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        // const anyContext = context as any\n        const screenPosition = context.bufferToScreen(\n            types.Position.create(this._line, this._diffPosition),\n        )\n\n        const pixelPosition = context.screenToPixel(screenPosition)\n\n        if (pixelPosition.pixelX < 0 || pixelPosition.pixelY < 0) {\n            return null\n        }\n\n        return (\n            <div\n                style={{\n                    position: \"absolute\",\n                    top: pixelPosition.pixelY.toString() + \"px\",\n                    left: pixelPosition.pixelX.toString() + \"px\",\n                }}\n            >\n                <TopArrow color={this._color} />\n                <BottomArrow color={this._color} />\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/DeleteCharactersStage.tsx",
    "content": "/**\n * DeleteCharactersStage.tsx\n *\n * Stage that visualizes characters that need to be deleted\n */\n\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport styled from \"styled-components\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nconst DeleteCharacterWrapper = styled.div`\n    background-color: rgba(255, 0, 0, 0.2);\n    color: white;\n    position: absolute;\n    border-bottom: 1px solid rgba(255, 0, 0, 0.8);\n`\nexport class DeleteCharactersStage implements ITutorialStage {\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(\n        private _goalName: string,\n        private _line: number,\n        private _startPosition: number,\n        private _charactersToDelete: string,\n    ) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        // NOTE: This stage is purely for rendering\n        return true\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        const screenPosition = context.bufferToScreen(\n            types.Position.create(this._line, this._startPosition),\n        )\n        const pixelPosition = context.screenToPixel(screenPosition)\n\n        if (pixelPosition.pixelX < 0 || pixelPosition.pixelY < 0) {\n            return null\n        }\n\n        const width = (context as any).fontPixelWidth\n        const height = (context as any).fontPixelHeight\n\n        return (\n            <DeleteCharacterWrapper\n                style={{\n                    left: pixelPosition.pixelX + \"px\",\n                    top: pixelPosition.pixelY + \"px\",\n                    width: this._charactersToDelete.length * width + \"px\",\n                    height: height + \"px\",\n                }}\n            />\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/FadeInLineStage.tsx",
    "content": "/**\n * FadeInLineStage.tsx\n *\n * Stage that visualizes characters that need to be deleted\n */\n\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport { configuration } from \"./../../../Configuration\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nimport { withProps } from \"./../../../../UI/components/common\"\n\nconst FuzzyFadeInKeyframes = keyframes`\n    0% { opacity: 0; -webkit-filter: blur(10px); }\n    100% { opacity: 1; }\n`\nconst Wrapper = withProps<{}>(styled.div)`\n    background-color: ${props => props.theme[\"editor.background\"]};\n    color: ${props => props.theme[\"editor.foreground\"]};\n    position: absolute;\n`\n\nconst FadeInWrapper = styled.div`\n    animation: ${FuzzyFadeInKeyframes} 0.4s linear forwards;\n\n    opacity: 0;\n`\nexport class FadeInLineStage implements ITutorialStage {\n    private _fontFamily: string\n    private _fontSize: string\n\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(private _goalName: string, private _line: number, private _characters: string) {\n        this._fontFamily = configuration.getValue(\"editor.fontFamily\")\n        this._fontSize = configuration.getValue(\"editor.fontSize\")\n    }\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        // NOTE: This stage is purely for rendering\n        return new Promise<boolean>(resolve => {\n            window.setTimeout(() => {\n                resolve(true)\n            }, 300)\n        })\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        const screenPosition = context.bufferToScreen(types.Position.create(0, 0))\n        const pixelPosition = context.screenToPixel(screenPosition)\n\n        if (pixelPosition.pixelX < 0 || pixelPosition.pixelY < 0) {\n            return null\n        }\n\n        const height = (context as any).fontPixelHeight\n\n        return (\n            <Wrapper\n                style={{\n                    left: pixelPosition.pixelX + \"px\",\n                    top: height * this._line + \"px\",\n                    height: height + \"px\",\n                    lineHeight: height + \"px\",\n                    fontFamily: this._fontFamily,\n                    fontSize: this._fontSize,\n                }}\n            >\n                <FadeInWrapper>{this._characters}</FadeInWrapper>\n            </Wrapper>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/InitializeBufferStage.tsx",
    "content": "/**\n * InitializeBufferStage\n *\n * Shows some whitespace on the 'grid'\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport class InitializeBufferStage implements ITutorialStage {\n    public get goalName(): string {\n        return null\n    }\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        await context.editor.neovim.command(\":set listchars=space:·,precedes:·,trail:·\")\n        await context.editor.neovim.command(\":set list!\")\n        await context.buffer.setLines(0, 9, [\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n            \"                    \",\n        ])\n\n        await context.buffer.setCursorPosition(0, 0)\n\n        return true\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/MoveToGoalStage.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nconst SpinnerKeyFrames = keyframes`\n    0% {transform: rotateY(0deg); }\n    100% { transform: rotateY(360deg); }\n`\n\nconst MoveToCharacterWrapper = styled.div`\n    background-color: rgba(255, 255, 255, 0.2);\n    position: absolute;\n    border-bottom: 1px solid rgba(255, 255, 255, 0.8);\n`\n\nconst TopArrow = styled.div`\n    animation: ${SpinnerKeyFrames} 2s linear infinite;\n    border-top: 8px solid white;\n    border-left: 6px solid transparent;\n    border-right: 6px solid transparent;\n    border-bottom: 6px solid transparent;\n    opacity: 0.8;\n    margin-left: -3px;\n    margin-top: 1px;\n`\n\nconst EntranceKeyFrames = keyframes`\n    0% { opacity: 0; }\n    100% { opacity: 1; }\n`\n\nconst CommonAnimation = `\n    animation-name: ${EntranceKeyFrames};\n    animation-duration: 0.4s;\n    animation-delay: 0.25s;\n    animation-timing-function: linear;\n    animation-fill-mode: forwards;\n    opacity: 0;\n`\n\nconst MoveToTopWrapper = styled.div`\n    ${CommonAnimation} position: absolute;\n    top: 0px;\n    left: 25%;\n    right: 25%;\n    height: 4em;\n    background-color: rgba(0, 0, 0, 0.8);\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nconst MoveToBottomWrapper = styled.div`\n    ${CommonAnimation} position: absolute;\n    bottom: 0px;\n    left: 25%;\n    right: 25%;\n    height: 4em;\n    background-color: rgba(0, 0, 0, 0.8);\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nexport class MoveToGoalStage implements ITutorialStage {\n    private _goalColumn: number\n    private _currentCursorLine: number = 0\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(private _goalName: string, private _line: number, private _column?: number) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        const cursorPosition = await (context.buffer as any).getCursorPosition()\n\n        this._currentCursorLine = cursorPosition.line\n        this._goalColumn =\n            typeof this._column === \"number\" ? this._column : cursorPosition.character\n\n        return (\n            cursorPosition.line === this._line &&\n            (cursorPosition.character === this._goalColumn || typeof this._column !== \"number\")\n        )\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        if (typeof this._goalColumn !== \"number\") {\n            return null\n        }\n\n        const screenPosition = context.bufferToScreen(\n            types.Position.create(this._line, this._goalColumn),\n        )\n        const pixelPosition = context.screenToPixel(screenPosition)\n\n        if (isNaN(pixelPosition.pixelX) || isNaN(pixelPosition.pixelY)) {\n            if (this._currentCursorLine > this._line) {\n                return <MoveToTopWrapper>Move up to line: {this._line + 1}</MoveToTopWrapper>\n            } else {\n                return (\n                    <MoveToBottomWrapper>Move down to line: {this._line + 1}</MoveToBottomWrapper>\n                )\n            }\n        }\n\n        const width = (context as any).fontPixelWidth\n        const height = (context as any).fontPixelHeight\n\n        return (\n            <div\n                style={{\n                    position: \"absolute\",\n                    top: pixelPosition.pixelY.toString() + \"px\",\n                    left: pixelPosition.pixelX.toString() + \"px\",\n                }}\n            >\n                <MoveToCharacterWrapper style={{ width: width + \"px\", height: height + \"px\" }} />\n                <TopArrow />\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/SetBufferStage.tsx",
    "content": "/**\n * ClearBufferStage\n */\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport class SetBufferStage implements ITutorialStage {\n    public get goalName(): string {\n        return null\n    }\n\n    constructor(private _lines: string[]) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        const allLines = context.buffer.lineCount\n        await context.buffer.setLines(0, allLines, this._lines)\n        return true\n    }\n\n    public render(): JSX.Element {\n        return null\n    }\n}\n\nexport class ClearBufferStage extends SetBufferStage {\n    constructor() {\n        super([])\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/SetCursorPositionStage.tsx",
    "content": "/**\n * SetCursorPositionStage.tsx\n */\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport class SetCursorPositionStage implements ITutorialStage {\n    public get goalName(): string {\n        return null\n    }\n\n    constructor(private _line: number = 0, private _column: number = 0) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        await context.buffer.setCursorPosition(this._line, this._column)\n        return true\n    }\n\n    public render(): JSX.Element {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/WaitForModeStage.tsx",
    "content": "/**\n * WaitForModeStage\n *\n * Stage that just waits for a mode to complete\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport class WaitForModeStage implements ITutorialStage {\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(private _goalName: string, private _mode: string) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        return context.editor.mode === this._mode\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/WaitForRegisterStage.tsx",
    "content": "/**\n * SetRegisterStage.tsx\n *\n * Stage that waits for expected register contents\n */\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport class WaitForRegisterStage implements ITutorialStage {\n    public get goalName(): string {\n        return this._goal\n    }\n\n    constructor(\n        private _goal: string,\n        private _contents: string,\n        private _register: string = '\"',\n    ) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        const contents = await context.editor.neovim.callFunction(\"getreg\", [this._register])\n        return contents === this._contents\n    }\n\n    public render(): JSX.Element {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/WaitForStateStage.tsx",
    "content": "/**\n * WaitForStateStage.tsx\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { ITutorialContext, ITutorialStage } from \"./../ITutorial\"\n\nexport class WaitForStateStage implements ITutorialStage {\n    public get goalName(): string {\n        return this._goalName\n    }\n\n    constructor(private _goalName: string, private _lines: string[]) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        // return false\n\n        const bufferLines = await context.buffer.getLines()\n\n        if (bufferLines.length === this._lines.length) {\n            return bufferLines.reduce((prev, curr, idx) => {\n                return curr === this._lines[idx] && prev\n            }, true)\n        }\n\n        return false\n\n        // const cursorPosition = await (context.buffer as any).getCursorPosition()\n\n        // this._goalColumn = this._column === null ? cursorPosition.character : this._column\n\n        // return cursorPosition.line === this._line && cursorPosition.character === this._goalColumn\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Stages/index.tsx",
    "content": "/**\n * Stages/index.tsx\n *\n * Entry point for stages, which are\n * building blocks for the tutorial levels\n */\n\nexport * from \"./CompositeStage\"\nexport * from \"./CorrectLineStage\"\nexport * from \"./FadeInLineStage\"\nexport * from \"./InitializeBufferStage\"\nexport * from \"./MoveToGoalStage\"\nexport * from \"./SetBufferStage\"\nexport * from \"./SetCursorPositionStage\"\nexport * from \"./WaitForRegisterStage\"\nexport * from \"./DeleteCharactersStage\"\nexport * from \"./WaitForModeStage\"\nexport * from \"./WaitForStateStage\"\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/TutorialBufferLayer.tsx",
    "content": "/**\n * TutorialBufferLayer.tsx\n *\n * Layer that handles the top-level rendering of the tutorial UI,\n * including the nested `NeovimEditor`, description, goals, etc.\n */\n\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport styled from \"styled-components\"\n\nimport { NeovimEditor } from \"./../../../Editor/NeovimEditor\"\n\nimport { getInstance as getPluginManagerInstance } from \"./../../../Plugins/PluginManager\"\nimport { getInstance as getColorsInstance } from \"./../../Colors\"\nimport { getInstance as getCompletionProvidersInstance } from \"./../../Completion\"\nimport { configuration } from \"./../../Configuration\"\nimport { getInstance as getDiagnosticsInstance } from \"./../../Diagnostics\"\nimport { getInstance as getLanguageManagerInstance } from \"./../../Language\"\nimport { getInstance as getMenuManagerInstance } from \"./../../Menu\"\nimport { getInstance as getOverlayInstance } from \"./../../Overlay\"\nimport { getInstance as getSnippetManagerInstance } from \"./../../Snippets\"\nimport { getThemeManagerInstance } from \"./../../Themes\"\nimport { getInstance as getTokenColorsInstance } from \"./../../TokenColors\"\nimport { windowManager } from \"./../../WindowManager\"\nimport { getInstance as getWorkspaceInstance } from \"./../../Workspace\"\n\nimport { Bold, withProps } from \"./../../../UI/components/common\"\nimport { FlipCard } from \"./../../../UI/components/FlipCard\"\nimport { StatusBar } from \"./../../../UI/components/StatusBar\"\n\nimport { ITutorialState, TutorialGameplayManager } from \"./TutorialGameplayManager\"\nimport { TutorialManager } from \"./TutorialManager\"\n\nimport { CompletionView } from \"./CompletionView\"\nimport { GameplayBufferLayer } from \"./GameplayBufferLayer\"\nimport { GoalView } from \"./GoalView\"\n\nimport { getInstance, Vector } from \"./../../Particles\"\n\nexport interface IGameplayCompletionInfo {\n    completed: boolean\n    keyPresses: number\n    timeInMilliseconds: number\n}\n\nconst DefaultCompletionInfo = {\n    completed: false,\n    keyPresses: -1,\n    timeInMilliseconds: 0,\n}\n\nexport interface IGameplayStateChangedEvent {\n    tutorialState: ITutorialState\n    completionInfo: IGameplayCompletionInfo\n    mode: string\n}\n\nexport class GameTracker {\n    private _startTime: Date\n    private _keyPresses: number\n\n    public start(): void {\n        this._startTime = new Date()\n        this._keyPresses = 0\n    }\n\n    public addKeyPress(pressCount: number) {\n        this._keyPresses += pressCount\n    }\n\n    public end(): IGameplayCompletionInfo {\n        return {\n            completed: true,\n            timeInMilliseconds: new Date().getTime() - this._startTime.getTime(),\n            keyPresses: this._keyPresses,\n        }\n    }\n}\n\nexport class TutorialBufferLayer implements Oni.BufferLayer {\n    private _editor: NeovimEditor\n    private _tutorialGameplayManager: TutorialGameplayManager\n    private _initPromise: Promise<void>\n\n    private _lastStage = -1\n    private _hasAddedLayer: boolean = false\n    private _currentTutorialId: string\n    private _lastTutorialState: ITutorialState\n    private _completionInfo: IGameplayCompletionInfo = DefaultCompletionInfo\n    private _element: HTMLElement\n    private _notes: JSX.Element[] = []\n    private _gameTracker: GameTracker = new GameTracker()\n    private _onStateChangedEvent: Event<ITutorialBufferLayerState> = new Event<\n        ITutorialBufferLayerState\n    >()\n\n    public get id(): string {\n        return \"oni.layer.tutorial\"\n    }\n\n    public get friendlyName(): string {\n        return \"Tutorial\"\n    }\n\n    constructor(private _tutorialManager: TutorialManager) {\n        // TODO: Streamline dependences for NeovimEditor, so it's easier just to spin one up..\n        this._editor = new NeovimEditor(\n            getColorsInstance(),\n            getCompletionProvidersInstance(),\n            configuration,\n            getDiagnosticsInstance(),\n            getLanguageManagerInstance(),\n            getMenuManagerInstance(),\n            getOverlayInstance(),\n            getPluginManagerInstance(),\n            getSnippetManagerInstance(),\n            getThemeManagerInstance(),\n            getTokenColorsInstance(),\n            getWorkspaceInstance(),\n        )\n\n        this._editor.autoFocus = false\n\n        this._editor.onNeovimQuit.subscribe(() => {\n            // TODO:\n            // Maybe add an achievement for 'quitting vim'?\n            // Close current buffer / tab?\n            alert(\"quit!\")\n        })\n\n        this._initPromise = this._editor.init([], {\n            loadInitVim: false,\n        })\n\n        this._tutorialGameplayManager = new TutorialGameplayManager(this._editor)\n\n        this._tutorialGameplayManager.onStateChanged.subscribe(state => {\n            this._lastTutorialState = state\n            this._onStateChangedEvent.dispatch({\n                tutorialState: state,\n                completionInfo: this._completionInfo,\n                mode: this._editor.mode,\n                notes: this._notes,\n            })\n\n            if (state.activeGoalIndex !== this._lastStage) {\n                this._lastStage = state.activeGoalIndex\n\n                if (this._element) {\n                    const cursor = this._element.getElementsByClassName(\"cursor\")\n                    if (cursor.length > 0) {\n                        const cursorElement = cursor[0]\n                        const position = cursorElement.getBoundingClientRect()\n\n                        this._spawnParticles(\"white\", { x: position.left, y: position.top })\n                    }\n                }\n            }\n        })\n\n        this._tutorialGameplayManager.onCompleted.subscribe(() => {\n            this._completionInfo = this._gameTracker.end()\n\n            this._onStateChangedEvent.dispatch({\n                tutorialState: this._lastTutorialState,\n                completionInfo: this._completionInfo,\n                mode: \"normal\",\n                notes: this._notes,\n            })\n\n            this._tutorialManager.notifyTutorialCompleted(this._currentTutorialId, {\n                time: this._completionInfo.timeInMilliseconds,\n                keyPresses: this._completionInfo.keyPresses,\n            })\n\n            if (this._element) {\n                const bounds = this._element.getBoundingClientRect()\n                const blue = \"rgb(97, 175, 239)\"\n\n                for (let i = 0; i < 8; i++) {\n                    this._spawnParticles(\n                        blue,\n                        {\n                            x: bounds.left + Math.random() * bounds.width,\n                            y: bounds.top + Math.random() * bounds.height,\n                        },\n                        { x: 300, y: 150 },\n                    )\n                }\n            }\n        })\n    }\n\n    public handleInput(key: string): boolean {\n        if (this._completionInfo.completed) {\n            const nextTutorial = this._tutorialManager.getNextTutorialId(this._currentTutorialId)\n\n            if (key === \"<space>\") {\n                this.startTutorial(this._currentTutorialId)\n            } else if (nextTutorial && key === \"<enter>\") {\n                this.startTutorial(nextTutorial)\n            } else {\n                // No tutorial left - we'll pass through\n                return false\n            }\n        } else {\n            this._editor.input(key)\n            this._gameTracker.addKeyPress(1)\n        }\n        return true\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return (\n            <TutorialBufferLayerView\n                editor={this._editor}\n                renderContext={context}\n                onStateChangedEvent={this._onStateChangedEvent}\n                innerRef={elem => (this._element = elem)}\n                onWillUnmount={() => this.stop()}\n            />\n        )\n    }\n\n    public async startTutorial(tutorialId: string): Promise<void> {\n        await this._initPromise\n        this._completionInfo = DefaultCompletionInfo\n        this._currentTutorialId = tutorialId\n        const tutorial = this._tutorialManager.getTutorial(tutorialId)\n\n        if (!this._hasAddedLayer) {\n            this._editor.activeBuffer.addLayer(\n                new GameplayBufferLayer(this._tutorialGameplayManager),\n            )\n            this._hasAddedLayer = true\n        }\n        this._notes = tutorial.notes || []\n\n        await this._editor.activeBuffer.setCursorPosition(0, 0)\n        await this._editor.neovim.command(\"stopinsert\")\n\n        this._tutorialGameplayManager.start(tutorial, this._editor.activeBuffer)\n        this._gameTracker.start()\n\n        windowManager.focusSplit(\"oni.window.0\")\n    }\n\n    public stop(): void {\n        this._tutorialGameplayManager.stop()\n    }\n\n    private _spawnParticles(\n        color: string,\n        position: Vector,\n        velocityVariance: Vector = { x: 100, y: 50 },\n    ): void {\n        const particles = getInstance()\n\n        if (!particles || !this._element) {\n            return\n        }\n\n        particles.createParticles(25, {\n            Position: position,\n            PositionVariance: { x: 10, y: 10 },\n            Velocity: { x: 0, y: -150 },\n            VelocityVariance: { x: 100, y: 50 },\n            Color: color,\n            StartOpacity: 1,\n            EndOpacity: 0,\n            Time: 1,\n        })\n    }\n}\n\nexport interface ITutorialBufferLayerViewProps {\n    renderContext: Oni.BufferLayerRenderContext\n    editor: NeovimEditor\n    onStateChangedEvent: IEvent<IGameplayStateChangedEvent>\n    innerRef: (elem: HTMLElement) => void\n\n    onWillUnmount: () => void\n}\n\nexport interface ITutorialBufferLayerState {\n    tutorialState: ITutorialState\n    completionInfo: IGameplayCompletionInfo\n    mode: string\n    notes: JSX.Element[]\n}\n\nconst TutorialWrapper = withProps<{}>(styled.div)`\n    position: relative;\n    width: 100%;\n    height: 100%;\n    background-color: ${p => p.theme[\"editor.background\"]};\n    color: ${p => p.theme[\"editor.foreground\"]};\n    overflow: auto;\n    pointer-events: all;\n\n    display: flex;\n    flex-direction: row;\n    `\n\nconst TutorialContentsWrapper = styled.div`\n    flex: 1 1 auto;\n    min-width: 600px;\n    max-width: 1000px;\n\n    margin-left: 2em;\n\n    display: flex;\n    flex-direction: column;\n`\n\nconst TutorialNotesWrapper = styled.div`\n    flex: 0 0 auto;\n    width: 250px;\n    border-left: 1px solid rgba(255, 255, 255, 0.2);\n    margin: 3em 0em;\n\n    display: flex;\n    flex-direction: column;\n`\n\nconst TutorialSectionWrapper = styled.div`\n    width: 75%;\n    max-width: 1000px;\n    flex: 0 0 auto;\n`\n\nconst MainTutorialSectionWrapper = styled.div`\n    flex: 1 1 auto;\n    width: 100%;\n    height: 100%;\n    min-height: 275px;\n\n    display: flex;\n    align-items: center;\n`\n\nconst PrimaryHeader = styled.div`\n    padding-top: 1em;\n    font-size: 2em;\n`\n\nconst SubHeader = styled.div`\n    font-size: 1.6em;\n`\n\nconst SectionHeader = styled.div`\n    font-size: 1.1em;\n    font-weight: bold;\n`\n\nconst Section = styled.div`\n    padding-top: 1em;\n    padding-bottom: 2em;\n`\n\nconst DescriptionWrapper = styled.div`\n    display: none;\n\n    @media (min-height: 800px) {\n        display: block;\n    }\n`\n\nexport interface IModeStatusBarItemProps {\n    mode: string\n}\n\nconst ModeStatusBarItem = withProps<IModeStatusBarItemProps>(styled.div)`\n    background-color: ${p => p.theme[\"highlight.mode.\" + p.mode + \".background\"]};\n    color: ${p => p.theme[\"highlight.mode.\" + p.mode + \".foreground\"]};\n    text-transform: uppercase;\n\n    height: 2em;\n    line-height: 2em;\n    padding: 0px 4px;\n`\n\nexport class TutorialBufferLayerView extends React.PureComponent<\n    ITutorialBufferLayerViewProps,\n    ITutorialBufferLayerState\n> {\n    constructor(props: ITutorialBufferLayerViewProps) {\n        super(props)\n\n        this.state = {\n            tutorialState: {\n                goals: [],\n                activeGoalIndex: -1,\n                metadata: null,\n            },\n            completionInfo: {\n                completed: false,\n                keyPresses: -1,\n                timeInMilliseconds: -1,\n            },\n            mode: \"normal\",\n            notes: [],\n        }\n    }\n\n    public componentDidMount(): void {\n        this.props.onStateChangedEvent.subscribe(newState => {\n            this.setState({\n                ...newState,\n            })\n        })\n    }\n\n    public componentWillUnmount(): void {\n        this.props.onWillUnmount()\n    }\n\n    public render(): JSX.Element {\n        if (!this.state.tutorialState || !this.state.tutorialState.metadata) {\n            return null\n        }\n\n        const title = this.state.tutorialState.metadata.name\n        const description = this.state.tutorialState.metadata.description\n\n        const activeIndex = this.state.tutorialState.activeGoalIndex\n\n        const goalsWithIndex = this.state.tutorialState.goals\n            .map((goal, idx) => ({\n                goalIndex: idx,\n                goal,\n            }))\n            .filter(gi => !!gi.goal)\n\n        let postActiveIndex = goalsWithIndex.findIndex(f => f.goalIndex === activeIndex)\n\n        if (this.state.completionInfo.completed) {\n            postActiveIndex = goalsWithIndex.length\n        }\n\n        const goalsToDisplay = goalsWithIndex.map((goal, postIndex) => {\n            const isCompleted = postActiveIndex > postIndex\n\n            let visible = false\n\n            if (postActiveIndex === 0) {\n                visible = postIndex < 3\n            } else if (postActiveIndex > goalsWithIndex.length - 3) {\n                visible = goalsWithIndex.length - postIndex <= 3\n            } else {\n                visible = Math.abs(postIndex - postActiveIndex) < 2\n            }\n\n            return (\n                <GoalView\n                    completed={isCompleted}\n                    description={goal.goal}\n                    active={goal.goalIndex === activeIndex}\n                    visible={visible}\n                />\n            )\n        })\n\n        const isFlipped = this.state.completionInfo.completed\n\n        return (\n            <TutorialWrapper>\n                <TutorialContentsWrapper>\n                    <TutorialSectionWrapper>\n                        <PrimaryHeader>Tutorial</PrimaryHeader>\n                        <SubHeader>{title}</SubHeader>\n                    </TutorialSectionWrapper>\n                    <MainTutorialSectionWrapper>\n                        <div\n                            style={{\n                                width: \"75%\",\n                                height: \"90%\",\n                                boxShadow: \"3px 7px 10px 7px rgba(0, 0, 0, 0.2)\",\n                            }}\n                            ref={this.props.innerRef}\n                        >\n                            <FlipCard\n                                isFlipped={isFlipped}\n                                front={\n                                    <div\n                                        style={{\n                                            width: \"100%\",\n                                            height: \"100%\",\n                                            display: \"flex\",\n                                            flexDirection: \"column\",\n                                        }}\n                                    >\n                                        <div\n                                            style={{\n                                                width: \"100%\",\n                                                height: \"100%\",\n                                                flex: \"1 1 auto\",\n                                            }}\n                                        >\n                                            {this.props.editor.render()}\n                                        </div>\n                                        <div style={{ flex: \"0 0 auto\" }}>\n                                            <StatusBar\n                                                items={[\n                                                    {\n                                                        alignment: 0,\n                                                        contents: <div />,\n                                                        id: \"tutorial.null\",\n                                                        priority: 0,\n                                                    },\n                                                    {\n                                                        alignment: 1,\n                                                        contents: (\n                                                            <ModeStatusBarItem\n                                                                mode={this.state.mode}\n                                                            >\n                                                                {this.state.mode}\n                                                            </ModeStatusBarItem>\n                                                        ),\n                                                        id: \"tutorial.mode\",\n                                                        priority: 0,\n                                                    },\n                                                ]}\n                                                fontFamily={configuration.getValue(\"ui.fontFamily\")}\n                                                fontSize={configuration.getValue(\"ui.fontSize\")}\n                                                enabled={!isFlipped}\n                                            />\n                                        </div>\n                                    </div>\n                                }\n                                back={\n                                    isFlipped ? (\n                                        <CompletionView\n                                            keyStrokes={this.state.completionInfo.keyPresses}\n                                            time={this.state.completionInfo.timeInMilliseconds}\n                                        />\n                                    ) : null\n                                }\n                            />\n                        </div>\n                    </MainTutorialSectionWrapper>\n                    <TutorialSectionWrapper>\n                        <DescriptionWrapper>\n                            <SectionHeader>Description:</SectionHeader>\n                            <Section>{description}</Section>\n                        </DescriptionWrapper>\n                        <SectionHeader>Goals:</SectionHeader>\n                        <Section style={{ height: \"200px\" }}>\n                            <div>{goalsToDisplay}</div>\n                        </Section>\n                        <Section />\n                    </TutorialSectionWrapper>\n                </TutorialContentsWrapper>\n                <TutorialNotesWrapper>\n                    <div style={{ textAlign: \"center\" }}>\n                        <Bold>Notes:</Bold>\n                    </div>\n                    <div>{this.state.notes}</div>\n                </TutorialNotesWrapper>\n            </TutorialWrapper>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/TutorialGameplayManager.ts",
    "content": "/**\n * TutorialManager\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { Event, IEvent } from \"oni-types\"\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./ITutorial\"\n\nexport interface ITutorialState {\n    metadata: ITutorialMetadata\n    renderFunc?: (context: Oni.BufferLayerRenderContext) => JSX.Element\n    activeGoalIndex: number\n    goals: string[]\n}\n\n/**\n * Class that manages the state / lifecycle of the tutorial\n * - Calls the 'tick' function\n * - Calls the 'render' function\n */\n\nexport const TICK_RATE = 50 /* 50 ms, or 20 times pers second */\n\nexport class TutorialGameplayManager {\n    private _activeTutorial: ITutorial\n    private _currentStageIdx: number\n    private _onStateChanged = new Event<ITutorialState>()\n    private _onCompleted = new Event<boolean>()\n    private _currentState: ITutorialState = null\n    private _onTick = new Event<void>()\n\n    private _isTickInProgress: boolean = false\n    private _buf: Oni.Buffer\n    private _pendingTimer: number | null = null\n\n    public get onStateChanged(): IEvent<ITutorialState> {\n        return this._onStateChanged\n    }\n\n    public get onCompleted(): IEvent<boolean> {\n        return this._onCompleted\n    }\n\n    public get onTick(): IEvent<void> {\n        return this._onTick\n    }\n\n    public get currentState(): ITutorialState {\n        return this._currentState\n    }\n\n    public get currentStage(): ITutorialStage {\n        return this._activeTutorial.stages[this._currentStageIdx]\n    }\n\n    public get currentTutorial(): ITutorial {\n        return this._activeTutorial\n    }\n\n    constructor(private _editor: Oni.Editor) {}\n\n    public start(tutorial: ITutorial, buffer: Oni.Buffer): void {\n        this._buf = buffer\n        this._currentStageIdx = 0\n        this._activeTutorial = tutorial\n\n        this._pendingTimer = window.setInterval(() => this._tick(), TICK_RATE)\n\n        this._tick()\n    }\n\n    public stop(): void {\n        if (this._pendingTimer) {\n            window.clearInterval(this._pendingTimer)\n            this._pendingTimer = null\n        }\n    }\n\n    private async _tick(): Promise<void> {\n        if (this._isTickInProgress) {\n            return\n        }\n\n        if (!this.currentStage) {\n            return\n        }\n\n        this._isTickInProgress = true\n\n        const result = await this.currentStage.tickFunction({\n            editor: this._editor,\n            buffer: this._buf,\n        })\n        this._onTick.dispatch()\n\n        this._isTickInProgress = false\n        if (result) {\n            this._currentStageIdx++\n\n            if (this._currentStageIdx >= this._activeTutorial.stages.length) {\n                this._onCompleted.dispatch(true)\n            }\n        }\n\n        const goalsToSend = this._activeTutorial.stages.map(f => f.goalName)\n\n        const newState: ITutorialState = {\n            metadata: this._activeTutorial.metadata,\n            goals: goalsToSend,\n            activeGoalIndex: this._currentStageIdx,\n            renderFunc: (context: Oni.BufferLayerRenderContext) =>\n                this.currentStage && this.currentStage.render\n                    ? this.currentStage.render(context)\n                    : null,\n        }\n        this._currentState = newState\n        this._onStateChanged.dispatch(newState)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/TutorialManager.ts",
    "content": "/**\n * TutorialManager\n */\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { EditorManager } from \"./../../EditorManager\"\nimport { WindowManager } from \"./../../WindowManager\"\n\nimport { IPersistentStore } from \"./../../../PersistentStore\"\n\nimport { ITutorial, ITutorialMetadata } from \"./ITutorial\"\nimport { TutorialBufferLayer } from \"./TutorialBufferLayer\"\n\nexport interface ITutorialPersistedState {\n    completedTutorialIds: string[]\n}\n\nexport interface ITutorialMetadataWithProgress {\n    tutorialInfo: ITutorialMetadata\n    completionInfo: ITutorialCompletionInfo\n}\n\nexport interface ITutorialCompletionInfo {\n    keyPresses: number\n    time: number /* milliseconds */\n}\n\nexport interface IdToCompletionInfo {\n    [tutorialId: string]: ITutorialCompletionInfo\n}\n\nexport interface IPersistedTutorialState {\n    completionInfo: IdToCompletionInfo\n}\n\nexport class TutorialManager {\n    private _tutorials: ITutorial[] = []\n    private _initPromise: Promise<IPersistedTutorialState>\n\n    private _persistedState: IPersistedTutorialState = { completionInfo: {} }\n    private _onTutorialCompletedEvent: Event<void> = new Event<void>()\n    private _onTutorialProgressChanged: Event<void> = new Event<void>()\n\n    public get onTutorialCompletedEvent(): IEvent<void> {\n        return this._onTutorialCompletedEvent\n    }\n\n    public get onTutorialProgressChangedEvent(): IEvent<void> {\n        return this._onTutorialProgressChanged\n    }\n\n    constructor(\n        private _editorManager: EditorManager,\n        private _persistentStore: IPersistentStore<IPersistedTutorialState>,\n        private _windowManager: WindowManager,\n    ) {}\n\n    public async start(): Promise<IPersistedTutorialState> {\n        if (this._initPromise) {\n            return this._initPromise\n        }\n\n        this._initPromise = this._persistentStore.get()\n\n        this._persistedState = await this._initPromise\n        this._onTutorialProgressChanged.dispatch()\n        return this._persistedState\n    }\n\n    public getTutorialInfo(): ITutorialMetadataWithProgress[] {\n        return this._getSortedTutorials().map(tut => ({\n            tutorialInfo: tut.metadata,\n            completionInfo: this._getCompletionState(tut.metadata.id),\n        }))\n    }\n\n    public getTutorial(id: string): ITutorial {\n        return this._tutorials.find(t => t.metadata.id === id)\n    }\n\n    public registerTutorial(tutorial: ITutorial): void {\n        this._tutorials.push(tutorial)\n    }\n\n    public async notifyTutorialCompleted(\n        id: string,\n        completionInfo: ITutorialCompletionInfo,\n    ): Promise<void> {\n        await this.start()\n        this._persistedState.completionInfo[id] = completionInfo\n        await this._persistentStore.set(this._persistedState)\n        this._onTutorialCompletedEvent.dispatch()\n        this._onTutorialProgressChanged.dispatch()\n    }\n\n    public async clearProgress(): Promise<void> {\n        await this.start()\n        this._persistedState = {\n            completionInfo: {},\n        }\n        await this._persistentStore.set(this._persistedState)\n        this._onTutorialProgressChanged.dispatch()\n    }\n\n    public getNextTutorialId(currentTutorialId?: string): string {\n        const sortedTutorials = this._getSortedTutorials()\n\n        if (!currentTutorialId) {\n            // Get first tutorial not completed\n            const nextIncompleteTutorial = sortedTutorials.find(f => {\n                return !this._persistedState.completionInfo[f.metadata.id]\n            })\n\n            return nextIncompleteTutorial ? nextIncompleteTutorial.metadata.id : null\n        }\n\n        const currentTuturial = sortedTutorials.findIndex(\n            tut => tut.metadata.id === currentTutorialId,\n        )\n        const nextTutorial = currentTuturial + 1\n\n        if (nextTutorial >= sortedTutorials.length) {\n            return null\n        }\n\n        return sortedTutorials[nextTutorial].metadata.id\n    }\n\n    public async startTutorial(id: string): Promise<void> {\n        const buf = await this._editorManager.activeEditor.openFile(\"oni://Tutorial\", {\n            openMode: Oni.FileOpenMode.Edit,\n        })\n        let tutorialLayer = (buf as any).getLayerById(\"oni.layer.tutorial\") as TutorialBufferLayer\n        if (!tutorialLayer) {\n            tutorialLayer = new TutorialBufferLayer(this)\n            buf.addLayer(tutorialLayer)\n        }\n\n        tutorialLayer.startTutorial(id)\n        // Focus the editor\n        const splitHandle = this._windowManager.getSplitHandle(this._editorManager\n            .activeEditor as any)\n        splitHandle.focus()\n    }\n\n    private _getSortedTutorials(): ITutorial[] {\n        return this._tutorials.sort((a, b) => {\n            return a.metadata.level - b.metadata.level\n        })\n    }\n\n    private _getCompletionState(id: string): ITutorialCompletionInfo {\n        return this._persistedState.completionInfo[id] || null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/BasicMovementTutorial.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\n// import { InitializeBufferStage, MoveToGoalStage } from \"./../Stages\"\n\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"In NORMAL mode, the 'l' key moves one character to the RIGHT...\"\nconst Line2 = \"...and 'h' moves one character to the LEFT.\"\nconst Line3 = \"'j' moves DOWN one line.\"\nconst Line4 = \"And 'k' moves UP one line.\"\nconst Line5 = \"Nice, you're a pro! Let's put it all together now.\"\n\nexport class BasicMovementTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1]),\n            new Stages.MoveToGoalStage(\"Use 'l' to move RIGHT to the goal\", 0, 10),\n            new Stages.SetBufferStage([Line1, Line2]),\n            new Stages.MoveToGoalStage(\"Use 'h' to move LEFT to the goal\", 0, 0),\n            new Stages.SetBufferStage([Line1, Line2, Line3]),\n            new Stages.MoveToGoalStage(\"Use 'j' to move DOWN to the goal\", 2, 0),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4]),\n            new Stages.MoveToGoalStage(\"Use 'k' to move UP to the goal\", 0, 0),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4, Line5]),\n            new Stages.MoveToGoalStage(\"Use h/j/k/l to move to the goal\", 4, 8),\n            new Stages.MoveToGoalStage(\"Use h/j/k/l to move to the goal\", 2, 1),\n            new Stages.MoveToGoalStage(\"Use h/j/k/l to move to the goal\", 0, 10),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.basic_movement\",\n            name: \"Motion: h, j, k, l\",\n            description:\n                \"To use Oni effectively in normal mode, you'll need to learn to move the cursor around! There are many ways to move the cursor, but the most basic is to use `h`, `j`, `k`, and `l`. These keys might seem strange at first, but they allow you to move the cursor without your fingers leaving the home row.\",\n            level: 110,\n        }\n    }\n\n    public get notes(): JSX.Element[] {\n        return [<Notes.HJKLKeys />]\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/BeginningsAndEndingsTutorial.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"Use the `$` key to move to the end of a line.\"\nconst Line2 = \"`0` moves to the beginning of the line.\"\nconst Line3 = \"    ...and `_` moves to the first character.\"\n\nexport class BeginningsAndEndingsTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1]),\n            new Stages.MoveToGoalStage(\n                \"Use '$' to move to the END of the line\",\n                0,\n                Line1.length - 1,\n            ),\n            new Stages.SetBufferStage([Line1, Line2]),\n            new Stages.MoveToGoalStage(\"Use '0' to move to the BEGINNING of the line\", 0, 0),\n            new Stages.MoveToGoalStage(\"Use `j` to move down to the next line\", 1),\n            new Stages.MoveToGoalStage(\n                \"Use '$' to move to the END of the line\",\n                1,\n                Line2.length - 1,\n            ),\n            new Stages.MoveToGoalStage(\"Use '0' to move to the BEGINNING of the line\", 1, 0),\n            new Stages.SetBufferStage([Line1, Line2, Line3]),\n            new Stages.MoveToGoalStage(\"Use `j` to move down to the next line\", 2),\n            new Stages.MoveToGoalStage(\n                \"Use '_' to move to the FIRST NON-WHITESPACE CHARACTER\",\n                2,\n                4,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use '$' to move to the END of the line\",\n                2,\n                Line3.length - 1,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use '_' to move to the FIRST NON-WHITESPACE CHARACTER\",\n                2,\n                4,\n            ),\n            new Stages.MoveToGoalStage(\"Use '0' to move to the BEGINNING of the line\", 2, 0),\n            new Stages.MoveToGoalStage(\n                \"Use '$' to move to the END of the line\",\n                2,\n                Line3.length - 1,\n            ),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.beginnings_and_endings\",\n            name: \"Start/End Motion: _, 0, $\",\n            description:\n                \"You don't need to keep hitting `w` or `b` when you need to go all the way to the beginning or the end of a line. You can use the `0` key to move to the very beginning a line, and `$` to move to the end. Also, `_` moves to the first non-whitespace character in the line, which is often more convenient than `0`.\",\n            level: 140,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [<Notes.HJKLKeys />, <Notes.ZeroKey />, <Notes.UnderscoreKey />, <Notes.DollarKey />]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/ChangeOperatorTutorial.tsx",
    "content": "/**\n * ChangeOperatorTutorial.tsx\n *\n * Tutorial that exercises the change operator\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"The change operator can be used for quikcly fixing typos\"\nconst Line1Marker = \"The change operator can be used for \".length\nconst Line1Pending = \"The change operator can be used for  fixing typos\"\nconst Line1Fixed = \"The change operator can be used for quickly fixing typos\"\nconst Line2 = \"Learning Vim can be tedious and repetitive\"\nconst Line2Fix1 = \"Learning Vim can be fun and repetitive\"\nconst Line2Fix2 = \"Learning Vim can be fun and exciting\"\n\nexport class ChangeOperatorTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 0, Line1Marker),\n            new Stages.WaitForStateStage(\"Fix the typo by hitting 'cw'\", [Line1Pending]),\n            new Stages.WaitForStateStage(\"Enter the word 'quickly'\", [Line1Fixed]),\n            new Stages.WaitForModeStage(\"Exit Insert mode by hitting <esc>\", \"normal\"),\n            new Stages.SetBufferStage([Line1Fixed, Line2]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, Line2.indexOf(\"tedious\")),\n            new Stages.WaitForStateStage(\"Change 'tedious' to 'fun'\", [Line1Fixed, Line2Fix1]),\n            new Stages.WaitForModeStage(\"Exit Insert mode by hitting <esc>\", \"normal\"),\n            new Stages.MoveToGoalStage(\n                \"Move to the goal marker\",\n                1,\n                Line2Fix1.indexOf(\"repetitive\"),\n            ),\n            new Stages.WaitForStateStage(\"Change 'repetitive' to 'exciting'\", [\n                Line1Fixed,\n                Line2Fix2,\n            ]),\n            new Stages.WaitForModeStage(\"Exit Insert mode by hitting <esc>\", \"normal\"),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.change_operator\",\n            name: \"Change Operator: c\",\n            description:\n                \"Now that you know about operators and motions pairing like a noun and a verb, we can start learning more operators.  The `c` operator allows you to _change_ text.  It deletes the selected text and immediately enters Insert mode so you can enter new text.  The text to be changed is defined by any motion just like the delete operator.  It might not seem very impressive right now but `c` will become more useful as you learn more motions.\",\n            level: 210,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.HJKLKeys />,\n            <Notes.ChangeOperatorKey />,\n            <Notes.ChangeWordKey />,\n            <Notes.EscKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/CopyPasteTutorial.tsx",
    "content": "/**\n * CopyPasteTutorial.tsx\n *\n * Tutorial for learning how to copy and paste text.\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"Like the 'd' operator, 'y' can be used to yank (copy) text\"\nconst Line2 = \"Any deleted text or yanked can then be pasted with 'p'\"\nconst Line2YankMarker = \"Any deleted \".length\nconst Line2PasteMarker = \"Any deleted text or yanked\".length\nconst Line2PostPaste1 = \"Any deleted text or yanked text can then be pasted with 'p'\"\nconst Line2PostPaste2 = \"text Any deleted text or yanked text can then be pasted with 'p'\"\n\nconst TransposeLine = \"Sipmle tpyos can aslo be fiexd with 'xp'\"\nconst TransposeLine1 = \"Simple tpyos can aslo be fiexd with 'xp'\"\nconst TransposeLine2 = \"Simple typos can aslo be fiexd with 'xp'\"\nconst TransposeLine3 = \"Simple typos can also be fiexd with 'xp'\"\nconst TransposeLine4 = \"Simple typos can also be fixed with 'xp'\"\n\nexport class CopyPasteTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1, Line2]),\n            new Stages.MoveToGoalStage(\"Move to the word 'text'\", 1, Line2YankMarker),\n            new Stages.WaitForRegisterStage(\"Yank this word with 'yw'\", \"text \"),\n            new Stages.MoveToGoalStage(\"Move after the word 'yanked'\", 1, Line2PasteMarker),\n            new Stages.WaitForStateStage(\"Paste after the cursor with 'p'\", [\n                Line1,\n                Line2PostPaste1,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the beginning of the line\", 1, 0),\n            new Stages.WaitForStateStage(\"Paste before the cursor with 'P'\", [\n                Line1,\n                Line2PostPaste2,\n            ]),\n            new Stages.WaitForRegisterStage(\n                \"Yank the entire line with 'yy'\",\n                Line2PostPaste2 + \"\\n\",\n            ),\n            new Stages.WaitForStateStage(\"Paste the yanked line below the cursor with 'p'\", [\n                Line1,\n                Line2PostPaste2,\n                Line2PostPaste2,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the top of the file\", 0, 0),\n            new Stages.WaitForStateStage(\"Paste _above_ the cursor with 'P'\", [\n                Line2PostPaste2,\n                Line1,\n                Line2PostPaste2,\n                Line2PostPaste2,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the next line\", 1, 0),\n            new Stages.WaitForStateStage(\"Deleting also copies text. Delete a line with 'dd'\", [\n                Line2PostPaste2,\n                Line2PostPaste2,\n                Line2PostPaste2,\n            ]),\n            new Stages.WaitForStateStage(\"Again, paste with 'p'\", [\n                Line2PostPaste2,\n                Line2PostPaste2,\n                Line1,\n                Line2PostPaste2,\n            ]),\n            new Stages.WaitForStateStage(\n                \"Copied text can be pasted multiple times, past again with 'p'\",\n                [Line2PostPaste2, Line2PostPaste2, Line1, Line1, Line2PostPaste2],\n            ),\n            new Stages.SetBufferStage([TransposeLine]),\n            new Stages.MoveToGoalStage(\"Move to the first typo\", 0, 2),\n            new Stages.WaitForStateStage(\n                \"Since deleted text is also copied, transposing characters is simple.  Try 'xp'\",\n                [TransposeLine1],\n            ),\n            new Stages.MoveToGoalStage(\"Move to the next typo\", 0, 8),\n            new Stages.WaitForStateStage(\"Again, fix the typo with 'xp'\", [TransposeLine2]),\n            new Stages.MoveToGoalStage(\"Move to the next typo\", 0, 18),\n            new Stages.WaitForStateStage(\"Again, fix the typo with 'xp'\", [TransposeLine3]),\n            new Stages.MoveToGoalStage(\"Move to the next typo\", 0, 27),\n            new Stages.WaitForStateStage(\"Again, fix the typo with 'xp'\", [TransposeLine4]),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.copy_paste\",\n            name: \"Copy & Paste: y, p\",\n            description:\n                \"Now that you know the delete and change operators, let's learn vim's final operator: `y`.  The `y` operator can be used to copy (\\\"yank\\\") text which can then be pasted with `p`.  Using `p` pastes _after_ the cursor, and `P` pastes _before_ the cursor.  The `y` operator behaves just like the `d` and `c` operators and can be paired with any motion.\",\n            level: 220,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.YankOperatorKey />,\n            <Notes.YankWordKey />,\n            <Notes.YankLineKey />,\n            <Notes.DeleteOperatorKey />,\n            <Notes.DeleteWordKey />,\n            <Notes.DeleteLineKey />,\n            <Notes.pasteKey />,\n            <Notes.PasteKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/DeleteCharacterTutorial.tsx",
    "content": "/**\n * DeleteCharacterTutorial.tsx\n *\n * Tutorial that runs through deleting a character.\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nimport { Bold } from \"./../../../../UI/components/common\"\n\nconst TutorialLine1Original = \"The coww jumped over the mmoon\"\nconst TutorialLine1CorrectA = \"The cow jumped over the mmoon\"\nconst TutorialLine1Correct = \"The cow jumped over the moon\"\n\nconst TutorialLine2FirstMarker = \"The b\".length - 1\nconst TutorialLine2Original = \"The bboy bougght the baskketball\"\nconst TutorialLine2SecondMarker = \"The boy boug\".length - 1\nconst TutorialLine2CorrectA = \"The boy bougght the baskketball\"\n\nconst TutorialLine2ThirdMarker = \"The boy bought the bask\".length - 1\nconst TutorialLine2CorrectB = \"The boy bought the baskketball\"\n\nconst TutorialLine2Correct = \"The boy bought the basketball\"\n\nconst TutorialLine3Original = \"Modal edditing is the ccats pajamas\"\n\nconst TutorialLine3FirstMarker = \"Modal ed\".length - 1\nconst TutorialLine3CorrectA = \"Modal editing is the ccats pajamas\"\n\nconst TutorialLine3SecondMarker = \"Modal editing is the c\".length - 1\nconst TutorialLine3Correct = \"Modal editing is the cats pajamas\"\n\nexport class DeleteCharacterTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([TutorialLine1Original]),\n            new Stages.MoveToGoalStage(\"Move to the first duplicated 'w' character\", 0, 6),\n            Stages.combine(\n                \"Delete the duplicated 'w' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 0, 6, \"w\"),\n                new Stages.WaitForStateStage(null, [TutorialLine1CorrectA]),\n            ),\n            new Stages.MoveToGoalStage(\n                \"Move to the first duplicated 'm' character\",\n                0,\n                TutorialLine1CorrectA.length - 5,\n            ),\n            Stages.combine(\n                \"Remove the duplicated 'm' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 0, TutorialLine1CorrectA.length - 5, \"m\"),\n                new Stages.WaitForStateStage(null, [TutorialLine1Correct]),\n            ),\n            new Stages.SetBufferStage([TutorialLine1Correct, TutorialLine2Original]),\n            new Stages.MoveToGoalStage(\n                \"Move to the first duplicated 'b' character\",\n                1,\n                TutorialLine2FirstMarker,\n            ),\n            Stages.combine(\n                \"Remove the duplicated 'b' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 1, TutorialLine2FirstMarker, \"b\"),\n                new Stages.WaitForStateStage(null, [TutorialLine1Correct, TutorialLine2CorrectA]),\n            ),\n            new Stages.MoveToGoalStage(\n                \"Move to the first duplicated 'g' character\",\n                1,\n                TutorialLine2SecondMarker,\n            ),\n            Stages.combine(\n                \"Remove the duplicated 'g' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 1, TutorialLine2SecondMarker, \"g\"),\n                new Stages.WaitForStateStage(null, [TutorialLine1Correct, TutorialLine2CorrectB]),\n            ),\n            new Stages.MoveToGoalStage(\n                \"Move to the first duplicated 'k' character\",\n                1,\n                TutorialLine2ThirdMarker,\n            ),\n            Stages.combine(\n                \"Remove the duplicated 'k' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 1, TutorialLine2ThirdMarker, \"g\"),\n                new Stages.WaitForStateStage(null, [TutorialLine1Correct, TutorialLine2Correct]),\n            ),\n            new Stages.SetBufferStage([\n                TutorialLine1Correct,\n                TutorialLine2Correct,\n                TutorialLine3Original,\n            ]),\n\n            new Stages.MoveToGoalStage(\n                \"Move to the first duplicated 'd' character\",\n                2,\n                TutorialLine3FirstMarker,\n            ),\n            Stages.combine(\n                \"Remove the duplicated 'd' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 2, TutorialLine3FirstMarker, \"d\"),\n                new Stages.WaitForStateStage(null, [\n                    TutorialLine1Correct,\n                    TutorialLine2Correct,\n                    TutorialLine3CorrectA,\n                ]),\n            ),\n\n            new Stages.MoveToGoalStage(\n                \"Move to the first duplicated 'c' character\",\n                2,\n                TutorialLine3SecondMarker,\n            ),\n            Stages.combine(\n                \"Remove the duplicated 'c' character by pressing `x`\",\n                new Stages.DeleteCharactersStage(null, 2, TutorialLine3SecondMarker, \"c\"),\n                new Stages.WaitForStateStage(null, [\n                    TutorialLine1Correct,\n                    TutorialLine2Correct,\n                    TutorialLine3Correct,\n                ]),\n            ),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorial.delete_character\",\n            name: \"Deleting a Character\",\n            description:\n                \"In normal mode, you can quickly delete characters. Move to the character (using h/j/k/l) and press `x` to delete. Correct the above lines without going to insert mode.\",\n            level: 190,\n        }\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.HJKLKeys />,\n            <Notes.KeyWithDescription\n                keyCharacter={\"x\"}\n                description={\n                    <span>\n                        In normal mode, <Bold>deletes the character</Bold> at the cursor position.\n                    </span>\n                }\n            />,\n        ]\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/DeleteOperatorTutorial.tsx",
    "content": "/**\n * DeleteOperatorTutorial.tsx\n *\n * Tutorial that exercises the delete operator\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"The delete operator is very useful!\"\nconst Line2a = \"--> Delete this line\"\n\nconst Line2b = \"--> You can delete the current line AND the one BELOW it,\"\nconst Line3b = \"--> using the `dj` command.\"\n\nconst Line2c = \"--> You can delete the current line AND the one ABOVE it,\"\nconst Line3c = \"--> using the `dk` command.\"\n\nconst Line2d = \"--> The delete operator works with other motions, too.\"\nconst Line3d = \"--> Let's try out `dw` - delete word. Delete the duplicate words below:\"\nconst Line4d = \"--> Help delete the duplicate duplicate words.\"\nconst Line4dCorrecta = \"--> Help delete the duplicate words.\"\nconst Line4dCorrectb = \"--> Help delete the words.\"\n\nconst Line2e = \"--> `d` followed by any motion will delete to that destination\"\nconst Line3e = \"--> This can allow for more precision when there aren't simple boundaries\"\nconst Line4e = \"--> public void somethingsomething(arg1, arg2, extra1, extra2)\"\nconst Line4eCorrecta = \"--> public void something(arg1, arg2, extra1, extra2)\"\nconst Line4eCorrectb = \"--> public void something(arg1, arg2)\"\n\nexport class DeleteOperatorTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1, Line2a]),\n            // new Stages.SetCursorPositionStage(0, 0),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, 0),\n            Stages.combine(\n                \"Delete the current line with 'dd'\",\n                new Stages.DeleteCharactersStage(null, 1, 0, Line2a),\n                new Stages.WaitForStateStage(null, [Line1]),\n            ),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line2b),\n                new Stages.FadeInLineStage(null, 2, Line3b),\n            ),\n            new Stages.SetBufferStage([Line1, Line2b, Line3b]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, 0),\n            Stages.combine(\n                \"Delete the current line, and the one below it, with 'dj'\",\n                new Stages.DeleteCharactersStage(null, 1, 0, Line2b),\n                new Stages.DeleteCharactersStage(null, 2, 0, Line3b),\n                new Stages.WaitForStateStage(null, [Line1]),\n            ),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line2c),\n                new Stages.FadeInLineStage(null, 2, Line3c),\n                new Stages.SetBufferStage([Line1, Line2c, Line3c]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 2, 0),\n            Stages.combine(\n                \"Delete the current line, and the one above it, with 'dk'\",\n                new Stages.DeleteCharactersStage(null, 1, 0, Line2c),\n                new Stages.DeleteCharactersStage(null, 2, 0, Line3c),\n                new Stages.WaitForStateStage(null, [Line1]),\n            ),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line2d),\n                new Stages.FadeInLineStage(null, 2, Line3d),\n                new Stages.FadeInLineStage(null, 3, Line4d),\n                new Stages.SetBufferStage([Line1, Line2d, Line3d, Line4d]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 3, 20),\n            Stages.combine(\n                \"Delete the duplicate word with 'dw'\",\n                new Stages.DeleteCharactersStage(null, 3, 20, \"duplicate\"),\n                new Stages.WaitForStateStage(null, [Line1, Line2d, Line3d, Line4dCorrecta]),\n            ),\n            Stages.combine(\n                \"Delete the word again with 'dw'\",\n                new Stages.DeleteCharactersStage(null, 3, 20, \"duplicate\"),\n                new Stages.WaitForStateStage(null, [Line1, Line2d, Line3d, Line4dCorrectb]),\n            ),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line2e),\n                new Stages.FadeInLineStage(null, 2, Line3e),\n                new Stages.FadeInLineStage(null, 3, Line4e),\n                new Stages.SetBufferStage([Line1, Line2e, Line3e, Line4e]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 3, 16),\n            Stages.combine(\n                \"Use 'dts' to delete to the next 's'\",\n                new Stages.DeleteCharactersStage(null, 3, 16, \"something\"),\n                new Stages.WaitForStateStage(null, [Line1, Line2e, Line3e, Line4eCorrecta]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 3, 36),\n            Stages.combine(\n                \"Use 'dt)' to delete to the ')'\",\n                new Stages.DeleteCharactersStage(null, 3, 36, \", extra1, extra2\"),\n                new Stages.WaitForStateStage(null, [Line1, Line2e, Line3e, Line4eCorrectb]),\n            ),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.delete_operator\",\n            name: \"Delete Operator: d\",\n            description:\n                \"We've stuck mostly with motions, but now we're going to learn about our first operator - delete (`d`). Operators are like _verbs_ in the vim world, and motions are like _nouns_. An operator can be paired with a motion - which means we can pair the `d` key with all sorts of motions - `dj` to delete the line and the line below, `dw` to delete a word, etc.\",\n            level: 200,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.HJKLKeys />,\n            <Notes.DeleteOperatorKey />,\n            <Notes.DeleteLineKey />,\n            <Notes.DeleteLineBelowKey />,\n            <Notes.DeleteLineAboveKey />,\n            <Notes.DeleteWordKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/DotCommandTutorial.tsx",
    "content": "/**\n * DotCommandTutorial.tsx\n *\n * Tutorial that teaches the dot (.) command\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst stage1Line1 = \"The dot (.) command can be used to repeat any single change.\"\nconst stage1Line2 = \"This line contains duplicate duplicate words\"\nconst stage1Line2a = \"This line contains duplicate words\"\n\nconst stage2Line1 =\n    \"A change can be anything that happens between leaving Normal Mode and returning to Normal Mode\"\nconst stage2Line2 = \"This line contains (an invalid) statement\"\nconst stage2Line2pending = \"This line contains () statement\"\nconst stage2Line2diff = \"This line contains (a different) statement\"\nconst stage2Line2a = \"This line contains (the fixed) statement\"\n\nexport class DotCommandTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([\n                stage1Line1,\n                stage1Line2,\n                stage1Line2,\n                stage1Line2,\n                stage1Line2,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, 19),\n            Stages.combine(\n                \"Remove the duplicate word using 'dw'\",\n                new Stages.DeleteCharactersStage(null, 1, 19, \"duplicate\"),\n                new Stages.WaitForStateStage(null, [\n                    stage1Line1,\n                    stage1Line2a,\n                    stage1Line2,\n                    stage1Line2,\n                    stage1Line2,\n                ]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 2, 19),\n            Stages.combine(\n                \"Repeat the 'dw' operation by just hitting '.'\",\n                new Stages.DeleteCharactersStage(null, 2, 19, \"duplicate\"),\n                new Stages.WaitForStateStage(null, [\n                    stage1Line1,\n                    stage1Line2a,\n                    stage1Line2a,\n                    stage1Line2,\n                    stage1Line2,\n                ]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 3, 19),\n            Stages.combine(\n                \"Again, hit '.'\",\n                new Stages.DeleteCharactersStage(null, 3, 19, \"duplicate\"),\n                new Stages.WaitForStateStage(null, [\n                    stage1Line1,\n                    stage1Line2a,\n                    stage1Line2a,\n                    stage1Line2a,\n                    stage1Line2,\n                ]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 4, 19),\n            Stages.combine(\n                \"Again, hit '.'\",\n                new Stages.DeleteCharactersStage(null, 4, 19, \"duplicate\"),\n                new Stages.WaitForStateStage(null, [\n                    stage1Line1,\n                    stage1Line2a,\n                    stage1Line2a,\n                    stage1Line2a,\n                    stage1Line2a,\n                ]),\n            ),\n            new Stages.SetBufferStage([\n                stage2Line1,\n                stage2Line2,\n                stage2Line2,\n                stage2Line2diff,\n                stage2Line2,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, 23),\n            Stages.combine(\n                \"Change the text within parentheses with 'ci('\",\n                new Stages.DeleteCharactersStage(null, 1, 20, \"an invalid\"),\n                new Stages.WaitForStateStage(null, [\n                    stage2Line1,\n                    stage2Line2pending,\n                    stage2Line2,\n                    stage2Line2diff,\n                    stage2Line2,\n                ]),\n            ),\n            new Stages.WaitForStateStage(\"Enter the text 'the fixed'\", [\n                stage2Line1,\n                stage2Line2a,\n                stage2Line2,\n                stage2Line2diff,\n                stage2Line2,\n            ]),\n            new Stages.WaitForModeStage(\"Hit <esc> to exit insert mode\", \"normal\"),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 2, 20),\n            Stages.combine(\n                \"Repeat the entire change with '.'\",\n                new Stages.DeleteCharactersStage(null, 2, 20, \"an invalid\"),\n                new Stages.WaitForStateStage(null, [\n                    stage2Line1,\n                    stage2Line2a,\n                    stage2Line2a,\n                    stage2Line2diff,\n                    stage2Line2,\n                ]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 3, 20),\n            Stages.combine(\n                \"Repeat the entire change with '.'\",\n                new Stages.DeleteCharactersStage(null, 3, 20, \"a different\"),\n                new Stages.WaitForStateStage(null, [\n                    stage2Line1,\n                    stage2Line2a,\n                    stage2Line2a,\n                    stage2Line2a,\n                    stage2Line2,\n                ]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 4, 20),\n            Stages.combine(\n                \"Repeat the entire change with '.'\",\n                new Stages.DeleteCharactersStage(null, 4, 20, \"an invalid\"),\n                new Stages.WaitForStateStage(null, [\n                    stage2Line1,\n                    stage2Line2a,\n                    stage2Line2a,\n                    stage2Line2a,\n                    stage2Line2a,\n                ]),\n            ),\n            Stages.combine(\n                \"Hit 'dd' to delete this line\",\n                new Stages.DeleteCharactersStage(null, 4, 0, stage2Line2a),\n                new Stages.WaitForStateStage(null, [\n                    stage2Line1,\n                    stage2Line2a,\n                    stage2Line2a,\n                    stage2Line2a,\n                ]),\n            ),\n            Stages.combine(\n                \"Hit '.' to repeat the delete\",\n                new Stages.DeleteCharactersStage(null, 3, 0, stage2Line2a),\n                new Stages.WaitForStateStage(null, [stage2Line1, stage2Line2a, stage2Line2a]),\n            ),\n            Stages.combine(\n                \"Hit '.' to repeat the delete\",\n                new Stages.DeleteCharactersStage(null, 2, 0, stage2Line2a),\n                new Stages.WaitForStateStage(null, [stage2Line1, stage2Line2a]),\n            ),\n            new Stages.MoveToGoalStage(\"Move to the top of the file\", 0, 0),\n            Stages.combine(\n                \"Hit '.' to repeat the delete\",\n                new Stages.DeleteCharactersStage(null, 0, 0, stage2Line1),\n                new Stages.WaitForStateStage(null, [stage2Line2a]),\n            ),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.dot_command\",\n            name: \"Repeat Command: .\",\n            description:\n                \"One of Vim's most powerful commands is performed by simply pressing period ('.').  The '.' command will repeat whatever operation you just performed.  Basically, it will repeat whatever keys you most recently hit to change the file.\",\n            level: 250,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [<Notes.DotKey />]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/InlineFindingTutorial.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\n// import { InitializeBufferStage, MoveToGoalStage } from \"./../Stages\"\n\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"Use 'f' to move to the next occurrence of a character within the same line.\"\nconst Line2 = \"And use 'F' to move to the previous occurrence of a character.\"\nconst Line3 = \"'t' is like 'f' except it moves to one spot before the character.\"\nconst Line4 = \"And 'T' is like 'F' except it moves one spot after.\"\nconst Line5 = \"Awesome! You can also use ';' to repeat the last f, t, F, or T.\"\nconst Line6 = \"Now use ',' to repeat the last f, t, F, or T in the opposite direction.\"\n\nexport class InlineFindingTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1]),\n            new Stages.MoveToGoalStage(\"Move to the nearest 'n' using 'fn'\", 0, 23),\n            new Stages.MoveToGoalStage(\"Move to the nearest 'a' using 'fa'\", 0, 42),\n            new Stages.SetBufferStage([Line1, Line2]),\n            new Stages.MoveToGoalStage(\"Move down a line\", 1, 42),\n            new Stages.MoveToGoalStage(\"Use 'Fm' to move BACKWARDS to the nearest 'm'\", 1, 15),\n            new Stages.MoveToGoalStage(\"Use 'Fs' to move BACKWARDS to the nearest 's'\", 1, 5),\n            new Stages.SetBufferStage([Line1, Line2, Line3]),\n            new Stages.MoveToGoalStage(\"Move down a line\", 2, 5),\n            new Stages.MoveToGoalStage(\"Use 'tx' to move to the character before 'x'\", 2, 16),\n            new Stages.MoveToGoalStage(\"Use 'tb' to move to the character before 'b'\", 2, 43),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4]),\n            new Stages.MoveToGoalStage(\"Move down a line\", 3, 43),\n            new Stages.MoveToGoalStage(\n                \"Use 'Tx' to move BACKWARDS to the character before 'x'\",\n                3,\n                22,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use 'Tl' to move BACKWARDS to the character before 'l'\",\n                3,\n                12,\n            ),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4, Line5]),\n            new Stages.MoveToGoalStage(\"Move down a line\", 4, 12),\n            new Stages.MoveToGoalStage(\"Use 'fe' to move to the nearest 'e'\", 4, 24),\n            new Stages.MoveToGoalStage(\"Use ';' to move to the next instance of 'e'\", 4, 34),\n            new Stages.MoveToGoalStage(\"Use ';' to move to the next instance of 'e'\", 4, 36),\n            new Stages.MoveToGoalStage(\"Use ';' to move to the next instance of 'e'\", 4, 42),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4, Line5, Line6]),\n            new Stages.MoveToGoalStage(\"Move down a line\", 5, 42),\n            new Stages.MoveToGoalStage(\"Use ',' to move to the previous instance of 'e'\", 5, 24),\n            new Stages.MoveToGoalStage(\"Use ',' to move to the previous instance of 'e'\", 5, 18),\n            new Stages.MoveToGoalStage(\"Use ',' to move to the previous instance of 'e'\", 5, 16),\n            new Stages.MoveToGoalStage(\"Use ',' to move to the previous instance of 'e'\", 5, 6),\n            new Stages.MoveToGoalStage(\"Move up a line\", 4, 6),\n            new Stages.MoveToGoalStage(\"Use 'te' to move before the nearest 'e'\", 4, 23),\n            new Stages.MoveToGoalStage(\"Use ';' to move before the next instance of 'e'\", 4, 33),\n            new Stages.MoveToGoalStage(\"Use ';' to move before the next instance of 'e'\", 4, 35),\n            new Stages.MoveToGoalStage(\"Use ';' to move before the next instance of 'e'\", 4, 41),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4, Line5, Line6]),\n            new Stages.MoveToGoalStage(\"Move down a line\", 5, 41),\n            new Stages.MoveToGoalStage(\n                \"Use ',' to move before the previous instance of 'e'\",\n                5,\n                25,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use ',' to move before the previous instance of 'e'\",\n                5,\n                19,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use ',' to move before the previous instance of 'e'\",\n                5,\n                17,\n            ),\n            new Stages.MoveToGoalStage(\"Use ',' to move before the previous instance of 'e'\", 5, 7),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.inline_finding\",\n            name: \"Character Find Motion: f, F, t, T\",\n            description:\n                \"Sometimes you need to move faster than 'h' and 'l' allow but need more control than 'w', 'e', and 'b', especially when using the operators you'll learn later. 'f' followed by any character moves to the next instance of that character, 'F' followed by any character moves backwards to the next instance of that character. Similarly, 't' and 'T' move forwards and backwards up to (but not on) the specified character. After performing a 'f', 'F', 't', or 'T' operation ';' and ',' allow you to repeat those motions in different directions.\",\n            level: 145,\n        }\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.fKey />,\n            <Notes.FKey />,\n            <Notes.tKey />,\n            <Notes.TKey />,\n            <Notes.RepeatKey />,\n            <Notes.RepeatOppositeKey />,\n        ]\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/InsertAndUndoTutorial.tsx",
    "content": "/**\n * InsertAndUndoTutorial.tsx\n *\n * Tutorial for undo and redo before we learn destructive changes\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst TutorialLine1Original = \"There is text msing this .\"\nconst TutorialLine1Correct = \"There is some text missing from this line.\"\n\nexport class InsertAndUndoTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([TutorialLine1Original, TutorialLine1Correct]),\n            new Stages.MoveToGoalStage(\"Move to the letter 't'\", 0, 9),\n            new Stages.WaitForModeStage(\"Press 'i' to enter insert mode\", \"insert\"),\n            new Stages.CorrectLineStage(\n                \"Add the missing word 'some '\",\n                0,\n                TutorialLine1Correct,\n                \"green\",\n                \"There is some \",\n            ),\n            new Stages.WaitForModeStage(\"Press '<esc>' to exit insert mode\", \"normal\"),\n            new Stages.MoveToGoalStage(\"Move to the letter 's'\", 0, 20),\n            new Stages.CorrectLineStage(\n                \"Correct the word: `msing` should be `missing`\",\n                0,\n                TutorialLine1Correct,\n                \"green\",\n                \"There is some text missing\",\n            ),\n            new Stages.CorrectLineStage(\n                \"Add the missing word 'from'\",\n                0,\n                TutorialLine1Correct,\n                \"green\",\n                \"There is some text missing from \",\n            ),\n            new Stages.CorrectLineStage(\n                \"Add the missing word 'line'\",\n                0,\n                TutorialLine1Correct,\n                \"green\",\n                \"There is some text missing from this line.\",\n            ),\n            new Stages.WaitForModeStage(\"Press '<esc>' to exit insert mode\", \"normal\"),\n            new Stages.WaitForStateStage(\"Press 'u' to undo the last change\", [\n                \"There is some text missing from this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'u' to undo another change\", [\n                \"There is some text missing this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'u' to undo yet another change\", [\n                \"There is some text msing this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'u' to undo yet another change\", [\n                \"There is text msing this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'Ctrl+r' to redo the last undo\", [\n                \"There is some text msing this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'Ctrl+r' to redo the next undo\", [\n                \"There is some text missing this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'Ctrl+r' to redo yet another undo\", [\n                \"There is some text missing from this .\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'Ctrl+r' to redo yet another undo\", [\n                \"There is some text missing from this line.\",\n                TutorialLine1Correct,\n            ]),\n            new Stages.WaitForStateStage(\"Press 'u' to undo the last change\", [\n                \"There is some text missing from this .\",\n                TutorialLine1Correct,\n            ]),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorial.undo_and_redo\",\n            name: \"Undo and Redo\",\n            description:\n                \"It's important to be able to switch between normal and insert mode, in order to edit text! Let's put together the cursor motion and insert mode from the previous tutorials.  If you make any mistakes, you can undo inserted text with 'u'.  To bring back an undo, hit 'Ctrl+r' to redo.\",\n            level: 170,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.HJKLKeys />,\n            <Notes.IKey />,\n            <Notes.EscKey />,\n            <Notes.UKey />,\n            <Notes.RedoKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/SearchInBufferTutorial.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\n// import { InitializeBufferStage, MoveToGoalStage } from \"./../Stages\"\n\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst EmptyLine = \"\"\n\n// Forward search lines\nconst Line1 = \"In NORMAL mode, the '/' key lets you search for a string.\"\nconst Line2 = \"It's a very powerful way to move your way inside a buffer quickly\"\nconst Line3 = \"The 'n' key lets you move to the next instance of the matched string.\"\nconst Line4 = \"Even if the match is way down, move here!\"\nconst Line5 = \"If you want to go the opposite way,\"\nconst Line6 = \"The 'N' key lets you move to the previous match.\"\n\n// Backward search lines\nconst Line7 = \"The '?' key will let you search backwards instead!\"\nconst Line8 = \"'?' searches backward, the 'n' and 'N' keys operate backward as well!\"\nconst Line9 = \"'N' will move you to the next instance going down\"\nconst Line10 = \"'n' will move you to the next instance going up\"\nconst Line11 = \"It may take you some practice to use reverse search\"\n\nexport class SearchInBufferTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            // Forward search\n            new Stages.SetBufferStage([Line1, Line2]),\n            new Stages.MoveToGoalStage(\n                \"Use '/' to enter search mode, type the word 'move', then hit <enter>\",\n                1,\n                28,\n            ),\n            new Stages.SetBufferStage([Line1, Line2, Line3]),\n            new Stages.MoveToGoalStage(\"Use 'n' to go to the next instance of 'move'\", 2, 21),\n            new Stages.SetBufferStage([Line1, Line2, Line3, EmptyLine, EmptyLine, Line4]),\n            new Stages.MoveToGoalStage(\"Use 'n' to go to the next instance of 'move'\", 5, 31),\n            new Stages.SetBufferStage([\n                Line1,\n                Line2,\n                Line3,\n                EmptyLine,\n                EmptyLine,\n                Line4,\n                Line5,\n                Line6,\n            ]),\n            new Stages.MoveToGoalStage(\"Use 'N' to go to the previous instance of 'move'\", 2, 21),\n            new Stages.MoveToGoalStage(\"Use 'N' to go to the previous instance of 'move'\", 1, 28),\n            // Backward search\n            new Stages.SetBufferStage([Line7, Line8, Line9, Line10, Line11]),\n            new Stages.SetCursorPositionStage(4, 33),\n            new Stages.MoveToGoalStage(\"Use '?' to search backwards for the word 'you'\", 4, 12),\n            new Stages.MoveToGoalStage(\n                \"Use 'n' to go to the next (backwards) instance of 'you'\",\n                3,\n                14,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use 'n' to go to the next (backwards) instance of 'you'\",\n                2,\n                14,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use 'n' to go to the next (backwards) instance of 'you'\",\n                0,\n                21,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use 'N' to go to the previous (backwards) instance of 'you'\",\n                2,\n                14,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use 'N' to go to the previous (backwards) instance of 'you'\",\n                3,\n                14,\n            ),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.find_across_buffer\",\n            name: \"Search Motion: /, ?, n, N\",\n            description:\n                \"To navigate a buffer efficiently, Oni lets you search for strings with `/` and `?`. `n` and `N` let you navigate quickly between the matches!\",\n            level: 160,\n        }\n    }\n\n    public get notes(): JSX.Element[] {\n        return [<Notes.SlashKey />, <Notes.QuestionKey />, <Notes.nKey />, <Notes.NKey />]\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/SwitchModeTutorial.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialContext, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Stages from \"./../Stages\"\n\nimport * as Notes from \"./../Notes\"\n\nexport class SwitchModeTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorial.switch_modes\",\n            name: \"Switching Modes\",\n            description:\n                \"Oni is a modal editor, which means the editor works in different modes. This can seem strange coming from other editors - where the only mode is inserting text. However, when working with text, you'll find that only a small percentage of the time you are typing - the majority of the time, you are navigating and editing, which is where normal mode is used. Let's practice switching to and from insert mode!\",\n            level: 100,\n        }\n    }\n\n    public get notes(): JSX.Element[] {\n        return [<Notes.IKey />, <Notes.EscKey />, <Notes.OKey />]\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    constructor() {\n        this._stages = [\n            new Stages.ClearBufferStage(),\n            new Stages.WaitForModeStage(\"Switch to INSERT mode by pressing 'i'\", \"insert\"),\n            new WaitForTextStage(\"Type some text!\"),\n            new Stages.WaitForModeStage(\"Switch back to NORMAL mode by pressing 'esc'\", \"normal\"),\n            {\n                goalName: \"Switch to insert mode on a new line by pressing 'o'\",\n                tickFunction: async (context: ITutorialContext): Promise<boolean> => {\n                    return context.editor.mode === \"insert\" && context.buffer.cursor.line >= 1\n                },\n            },\n            new WaitForTextStage(\"Type some more text!\"),\n            new Stages.WaitForModeStage(\"Switch back to NORMAL mode by pressing 'esc'\", \"normal\"),\n        ]\n    }\n}\n\nexport class WaitForTextStage implements ITutorialStage {\n    private _characterCount: number = 0\n\n    public get goalName(): string {\n        return `${this._goalName} [${this._characterCount}/4 characters entered]`\n    }\n\n    constructor(private _goalName: string) {}\n\n    public async tickFunction(context: ITutorialContext): Promise<boolean> {\n        const [line] = await context.buffer.getLines(\n            context.buffer.cursor.line,\n            context.buffer.cursor.line + 1,\n        )\n\n        this._characterCount = !!line ? line.length : 0\n\n        return line && line.length > 3\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/TargetsVimPluginTutorial.tsx",
    "content": "/**\n *\n * Tutorial that exercises the targets.vim plugin\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1a = \"The Targets.vim plugin is very useful!\"\nconst Line1b = \"It was created by Christian Wellenbrock.\"\nconst Line1c1 = \"Targets.vim adds text objects for additional (operations).\"\nconst Line1c2 = \"Targets.vim adds text objects for additional (foo).\"\n\nconst Line2a1 = \"'cin(' changes inside the next pair of (parenthesis).\"\nconst Line2a2 = \"'cin(' changes inside the next pair of ().\"\nconst Line2a3 = \"'cin(' changes inside the next pair of (foo).\"\nconst Line2b1 = \"'can(' changes the next pair of (parenthesis).\"\nconst Line2b2 = \"'can(' changes the next pair of bar.\"\nconst Line2c = \"Replacing 'n' with 'l' will change the previous pair.\"\nconst Line2d1 = \"Omitting either will change the (current pair) or the (next).\"\nconst Line2d2 = \"Omitting either will change the  or the (next).\"\nconst Line2d3 = \"Omitting either will change the  or the again.\"\n\nconst Line3a1 = \"Quote objects can 'also' be used.\"\nconst Line3a2 = \"Quote objects can '' be used.\"\nconst Line3b1 = '\\'cIn\"\\' changes the first characters inside of \" quotes \".'\nconst Line3b2 = '\\'cIn\"\\' changes the first characters inside of \" test \".'\nconst Line3c = '\\'cAn\"\\' changes around the \"quotes\" .'\n\nconst Line4a1 = \"'din,' will delete inside the next list, with, commas.\"\nconst Line4a2 = \"'din,' will delete inside the next list,, commas.\"\nconst Line4b = \"Many different seperators are possible.\"\nconst Line4c1 = \"Some applications you might consider not_a_list.\"\nconst Line4c2 = \"Some applications you might consider not__list.\"\n\nconst Line5a = \"Replacing the text character with 'a' will find the next programming argument.\"\nconst Line5b1 = \"'cina' will change inside the (next, argument).\"\nconst Line5b2 = \"'cina' will change inside the (fixed, argument).\"\nconst Line5c1 = \"'dana' deletes the (next, argument)\"\nconst Line5c2 = \"'dana' deletes the (argument)\"\n\nconst Line6a = \"These are only a brief overview of Targets.vim.\"\nconst Line6b = \"More advanced features can be found on its github repository.\"\nconst Line6c = \"https://github.com/wellle/targets.vim\"\n\nexport class TargetsVimPluginTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1a, Line1b, Line1c1]),\n            new Stages.SetCursorPositionStage(0, 0),\n            new Stages.MoveToGoalStage(\"Use 'cin(' to change inside the next parenthesis\", 2, 46),\n            new Stages.WaitForStateStage(\"Type 'foo'\", [Line1a, Line1b, Line1c2]),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line2a1),\n                new Stages.FadeInLineStage(null, 2, Line2b1),\n                new Stages.FadeInLineStage(null, 3, Line2c),\n                new Stages.SetBufferStage([Line2a1, Line2b1, Line2c, Line2d1]),\n            ),\n            new Stages.SetCursorPositionStage(0, 7),\n            Stages.combine(\n                \"Use 'din(' to delete inside the next parenthesis\",\n                new Stages.DeleteCharactersStage(null, 0, 40, \"parenthesis\"),\n                new Stages.WaitForStateStage(null, [Line2a2, Line2b1, Line2c, Line2d1]),\n            ),\n            new Stages.SetCursorPositionStage(1, 7),\n            new Stages.MoveToGoalStage(\"Use 'can(' to change the next parenthesis\", 1, 32),\n            new Stages.WaitForStateStage(\"Type 'bar'\", [Line2a2, Line2b2, Line2c, Line2d1]),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            new Stages.MoveToGoalStage(\"Use 'cil(' to change inside the last parenthesis\", 0, 40),\n            new Stages.WaitForStateStage(\"Type 'foo'\", [Line2a3, Line2b2, Line2c, Line2d1]),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            new Stages.SetCursorPositionStage(3, 34),\n            Stages.combine(\n                \"Use 'da(' to delete the current parenthesis\",\n                new Stages.DeleteCharactersStage(null, 3, 32, \"(current pair)\"),\n                new Stages.WaitForStateStage(null, [Line2a3, Line2b2, Line2c, Line2d2]),\n            ),\n            new Stages.MoveToGoalStage(\"Use 'ca(' to change the next parenthesis\", 3, 40),\n            new Stages.WaitForStateStage(\"Type 'again'\", [Line2a3, Line2b2, Line2c, Line2d3]),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line3a1),\n                new Stages.FadeInLineStage(null, 2, Line3b1),\n                new Stages.SetBufferStage([Line3a1, Line3b1, Line3c]),\n            ),\n            new Stages.SetCursorPositionStage(0, 0),\n            Stages.combine(\n                \"Use din' to delete inside the next single quotes\",\n                new Stages.DeleteCharactersStage(null, 0, 19, \"also\"),\n                new Stages.WaitForStateStage(null, [Line3a2, Line3b1, Line3c]),\n            ),\n            new Stages.SetCursorPositionStage(1, 7),\n            new Stages.MoveToGoalStage(\n                'Use cIn\" to change the first non-whitespace characters inside the next double quotes',\n                1,\n                48,\n            ),\n            new Stages.WaitForStateStage(\"Type 'test'\", [Line3a2, Line3b2, Line3c]),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            new Stages.SetCursorPositionStage(2, 7),\n            new Stages.MoveToGoalStage('Use cAn\" to change the next double quotes', 2, 26),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line4a1),\n                new Stages.FadeInLineStage(null, 2, Line4b),\n                new Stages.SetBufferStage([Line4a1, Line4b, Line4c1]),\n            ),\n            new Stages.SetCursorPositionStage(0, 7),\n            Stages.combine(\n                \"Use 'din,' to delete the next item in the list\",\n                new Stages.DeleteCharactersStage(null, 0, 40, \" with\"),\n                new Stages.WaitForStateStage(null, [Line4a2, Line4b, Line4c1]),\n            ),\n            Stages.combine(\n                \"Use 'din_' to delete inside the next underline in the variable\",\n                new Stages.DeleteCharactersStage(null, 2, 41, \"a\"),\n                new Stages.WaitForStateStage(null, [Line4a2, Line4b, Line4c2]),\n            ),\n            new Stages.MoveToGoalStage(\"Type gg to go to the beginning.\", 0, 0),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line5a),\n                new Stages.FadeInLineStage(null, 2, Line5b1),\n                new Stages.SetBufferStage([Line5a, Line5b1, Line5c1]),\n            ),\n            new Stages.SetCursorPositionStage(0, 0),\n            new Stages.MoveToGoalStage(\"Use 'cina' to change the next programming argument\", 1, 31),\n            new Stages.WaitForStateStage(\"Type 'fixed'\", [Line5a, Line5b2, Line5c1]),\n            new Stages.WaitForModeStage(\"Press ESC to go back to normal mode\", \"normal\"),\n            new Stages.MoveToGoalStage(\"Move to the next line\", 2, 7),\n            Stages.combine(\n                \"Use 'dana' to delete the next argument\",\n                new Stages.DeleteCharactersStage(null, 2, 20, \"next, \"),\n                new Stages.WaitForStateStage(null, [Line5a, Line5b2, Line5c2]),\n            ),\n            new Stages.MoveToGoalStage(\"Type gg to go to the beginning.\", 0, 0),\n            Stages.combine(\n                null,\n                new Stages.FadeInLineStage(null, 1, Line6a),\n                new Stages.FadeInLineStage(null, 2, Line6b),\n                new Stages.SetBufferStage([Line6a, Line6b, Line6c]),\n            ),\n            new Stages.SetCursorPositionStage(2, 0),\n            new Stages.MoveToGoalStage(\"Type gg to go to the beginning.\", 0, 0),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.targets_plugin\",\n            name: \"Targets.vim plugin\",\n            description:\n                'Targets.vim is a plugin installed by default to help move between pairs of characters such as (), {}, or \"\".  It does this by adding various text objects to operate on and expand simple commands like \\'di\"\\'.',\n            level: 300,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.Targetckey />,\n            <Notes.Targetdkey />,\n            <Notes.Targetikey />,\n            <Notes.Targetakey />,\n            <Notes.TargetIkey />,\n            <Notes.TargetAkey />,\n            <Notes.Targetnkey />,\n            <Notes.Targetlkey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/TextObjectsTutorial.tsx",
    "content": "/**\n * TextObjectsTutorial.tsx\n *\n * Tutorial to teach text objects\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst stage1line1 = \"Text objects typically have delimiters like ( ) and { }\"\nconst stage1line2 = \"This sentence has a phrase (within some parentheses) for testing\"\nconst stage1line2a = \"This sentence has a phrase () for testing\"\nconst stage1line2b = \"This sentence has a phrase  for testing\"\nconst stage1line2c =\n    \"This sentence has a phrase (within some parentheses) for testingwithin some parentheses\"\nconst stage1line2d = \"This sentence has a phrase (this is a test) for testing\"\n\nconst stage2line1 = \"Text objects can also span multiple lines\"\nconst stage2line2 = \"{\"\nconst stage2line3 = \"   these are mostly useful\"\nconst stage2line4 = \"   when editing code\"\nconst stage2line5 = \"}\"\n\nconst stage3line1 =\n    \"Text Objects aren't limited to single character delimiters; they also work with HTML!\"\nconst stage3line2 = \"<html>\"\nconst stage3line3 = \"   <p>\"\nconst stage3line4 = \"      <span>here is some text</span>\"\nconst stage3line4a = \"      <span></span>\"\nconst stage3line4b = \"      \"\nconst stage3line5 = \"   </p>\"\nconst stage3line5a = \"   \"\nconst stage3line6 = \"</html>\"\n\nconst stage4line1 = \"There are many other Text Objects we can manipulate\"\nconst stage4line2 = \"[ there ] ( are ) { many } < text > objects ' to ' \\\" try \\\"\"\nconst stage4line2a = \"[] ( are ) { many } < text > objects ' to ' \\\" try \\\"\"\nconst stage4line2b = \"[] () { many } < text > objects ' to ' \\\" try \\\"\"\nconst stage4line2c = \"[] () {} < text > objects ' to ' \\\" try \\\"\"\nconst stage4line2d = \"[] () {} <> objects ' to ' \\\" try \\\"\"\nconst stage4line2e = \"[] () {} <>  ' to ' \\\" try \\\"\"\nconst stage4line2f = \"[] () {} <>  '' \\\" try \\\"\"\nconst stage4line2g = \"[] () {} <>  '' \\\"\\\"\"\n\nexport class TextObjectsTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([stage1line1, stage1line2]),\n            new Stages.MoveToGoalStage(\"Move inside the parentheses\", 1, 41),\n            Stages.combine(\n                \"Use 'di(' to delete everything within the parentheses\",\n                new Stages.DeleteCharactersStage(null, 1, 28, \"within some parentheses\"),\n                new Stages.WaitForStateStage(null, [stage1line1, stage1line2a]),\n            ),\n            new Stages.WaitForStateStage(\"Notice it left the parentheses.  Hit 'u' to undo\", [\n                stage1line1,\n                stage1line2,\n            ]),\n            new Stages.MoveToGoalStage(\"Move inside the parentheses\", 1, 41),\n            Stages.combine(\n                \"Use 'da(' to delete the parentheses and everything within\",\n                new Stages.DeleteCharactersStage(null, 1, 27, \"(within some parentheses)\"),\n                new Stages.WaitForStateStage(null, [stage1line1, stage1line2b]),\n            ),\n            new Stages.WaitForStateStage(\"Hit 'u' to undo\", [stage1line1, stage1line2]),\n            new Stages.MoveToGoalStage(\"Move inside the parentheses\", 1, 41),\n            new Stages.WaitForRegisterStage(\n                \"Use 'yi(' to yank everything with the parentheses\",\n                \"within some parentheses\",\n            ),\n            new Stages.MoveToGoalStage(\"Move to the end of the line\", 1, 63),\n            new Stages.WaitForStateStage(\"Paste from the clipboard with 'p'\", [\n                stage1line1,\n                stage1line2c,\n            ]),\n            new Stages.WaitForStateStage(\"Hit 'u' to undo\", [stage1line1, stage1line2]),\n            new Stages.MoveToGoalStage(\"Move inside the parentheses\", 1, 41),\n            Stages.combine(\n                \"Use 'ci(' to change everything within the parentheses\",\n                new Stages.WaitForModeStage(null, \"insert\"),\n                new Stages.WaitForStateStage(null, [stage1line1, stage1line2a]),\n            ),\n            new Stages.WaitForStateStage(\"Type 'this is a test'\", [stage1line1, stage1line2d]),\n            new Stages.WaitForModeStage(\"Hit <esc> to exit insert mode\", \"normal\"),\n\n            new Stages.SetBufferStage([\n                stage2line1,\n                stage2line2,\n                stage2line3,\n                stage2line4,\n                stage2line5,\n            ]),\n            new Stages.MoveToGoalStage(\"Move inside the curly brackets\", 2, 14),\n            Stages.combine(\n                \"Use 'vi{' to select everything within the curly brackets\",\n                new Stages.MoveToGoalStage(null, 3, 19),\n                new Stages.WaitForModeStage(null, \"visual\"),\n            ),\n            new Stages.WaitForModeStage(\"Hit <esc> to exit visual mode\", \"normal\"),\n            Stages.combine(\n                \"Use 'va{' to select everything including the curly brackets\",\n                new Stages.MoveToGoalStage(null, 4, 0),\n                new Stages.WaitForModeStage(null, \"visual\"),\n            ),\n            new Stages.WaitForModeStage(\"Hit <esc> to exit visual mode\", \"normal\"),\n\n            new Stages.SetBufferStage([\n                stage3line1,\n                stage3line2,\n                stage3line3,\n                stage3line4,\n                stage3line5,\n                stage3line6,\n            ]),\n            new Stages.MoveToGoalStage(\"Move inside the HTML tag\", 3, 20),\n            Stages.combine(\n                \"Use 'dit' to delete everything within the <span> tag\",\n                new Stages.DeleteCharactersStage(null, 3, 12, \"here is some text\"),\n                new Stages.WaitForStateStage(null, [\n                    stage3line1,\n                    stage3line2,\n                    stage3line3,\n                    stage3line4a,\n                    stage3line5,\n                    stage3line6,\n                ]),\n            ),\n            new Stages.WaitForStateStage(\"Hit 'u' to undo\", [\n                stage3line1,\n                stage3line2,\n                stage3line3,\n                stage3line4,\n                stage3line5,\n                stage3line6,\n            ]),\n            Stages.combine(\n                \"Use 'dat' to delete the <span> tag and its contents\",\n                new Stages.DeleteCharactersStage(null, 3, 6, \"<span>here is some text</span>\"),\n                new Stages.WaitForStateStage(null, [\n                    stage3line1,\n                    stage3line2,\n                    stage3line3,\n                    stage3line4b,\n                    stage3line5,\n                    stage3line6,\n                ]),\n            ),\n            Stages.combine(\n                \"Use 'dat' to delete the <p> tag and its contents\",\n                new Stages.DeleteCharactersStage(null, 2, 3, \"<p>\"),\n                new Stages.DeleteCharactersStage(null, 3, 0, \"      \"),\n                new Stages.DeleteCharactersStage(null, 4, 0, \"   </p>\"),\n                new Stages.WaitForStateStage(null, [\n                    stage3line1,\n                    stage3line2,\n                    stage3line5a,\n                    stage3line6,\n                ]),\n            ),\n\n            new Stages.SetBufferStage([stage4line1, stage4line2]),\n            new Stages.MoveToGoalStage(\"Move to the next line\", 1, 0),\n            Stages.combine(\n                \"Try 'di['\",\n                new Stages.DeleteCharactersStage(null, 1, 1, \" there \"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2a]),\n            ),\n            Stages.combine(\n                \"Try 'di('\",\n                new Stages.DeleteCharactersStage(null, 1, 4, \" are \"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2b]),\n            ),\n            Stages.combine(\n                \"Try 'di{'\",\n                new Stages.DeleteCharactersStage(null, 1, 7, \" many \"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2c]),\n            ),\n            Stages.combine(\n                \"Try 'di<'\",\n                new Stages.DeleteCharactersStage(null, 1, 10, \" text \"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2d]),\n            ),\n            new Stages.MoveToGoalStage(\"Move inside the word 'objects'\", 1, 15),\n            Stages.combine(\n                \"Try 'diw'\",\n                new Stages.DeleteCharactersStage(null, 1, 12, \"objects\"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2e]),\n            ),\n            Stages.combine(\n                \"Try di'\",\n                new Stages.DeleteCharactersStage(null, 1, 14, \" to \"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2f]),\n            ),\n            Stages.combine(\n                'Try di\"',\n                new Stages.DeleteCharactersStage(null, 1, 17, \" try \"),\n                new Stages.WaitForStateStage(null, [stage4line1, stage4line2g]),\n            ),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorial.text_objects\",\n            name: \"Text Objects: i, a\",\n            description:\n                'Everything you\\'ve learned so far has involved motions from the current cursor position to a destination of some kind.  Now it\\'s time to learn about Text Objects, blocks of text with their own starting and ending characters.  Text Objects can be manipulated with the operators you\\'ve already learned such as `y`, `c`, `d`, and `v`.  In general, defining a text obect with `i` will be the \"inner\" object, ignoring the text object boundary characters.  Defining a text object with `a` will be \"an\" object, including the text object boundaries.',\n            level: 240,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.ChangeOperatorKey />,\n            <Notes.DeleteOperatorKey />,\n            <Notes.YankOperatorKey />,\n            <Notes.VisualModeKey />,\n            <Notes.innerTextObjectKey />,\n            <Notes.aTextObjectKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/VerticalMovementTutorial.tsx",
    "content": "/**\n * Vertical Movement Tutorial\n */\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nexport class VerticalMovementTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        const lines = []\n        for (let i = 1; i < 151; i++) {\n            lines.push(`This is line ${i} of a large file!`)\n        }\n\n        this._stages = [\n            new Stages.SetBufferStage(lines),\n            new Stages.MoveToGoalStage(\"Use 'G' to move to the BOTTOM of the file.\", 149, 0),\n            new Stages.MoveToGoalStage(\"Use 'gg' to move to the TOP of the file\", 0, 0),\n            new Stages.MoveToGoalStage(\"Use 50G to move line 50\", 49, 0),\n            new Stages.MoveToGoalStage(\"Use 100G to move line 100\", 99, 0),\n            new Stages.MoveToGoalStage(\"Move to the bottom of the file\", 149, 0),\n            new Stages.MoveToGoalStage(\"Move to the top of the file\", 0, 0),\n            new Stages.MoveToGoalStage(\"Move to line 125\", 124, 0),\n            new Stages.MoveToGoalStage(\"Move back to the top of the file\", 0, 0),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.vertical_movement\",\n            name: \"File Motion: gg, G\",\n            description:\n                \"When working with large files, it's very helpful to be able to quickly move to the top or bottom of the file, as well as to a particular line number. `gg`, `G`, and `<n>G` can help us here!\",\n            level: 150,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [<Notes.GKey />, <Notes.GGKey />, <Notes.XGKey />]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/VisualModeTutorial.tsx",
    "content": "/**\n * VisualModeTutorial.tsx\n *\n * Tutorial for learning how to select text in visual mode.\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"Text can be selectedselected with 'v'.\"\nconst Line2 = \"Selected text can then be (y)anked, (c)hanged, or (d)eleted with a single keypress\"\nconst Line3 = \"To select entire lines, use 'V' to include line-ending characters.\"\nconst Line4 = \"Selected lines can also be  with a single keypress\"\nconst Line1Marker = \"Text can be \".length\nconst Line1Marker2 = \"Text can be selecte\".length\nconst Line1Change = \"Text can be selected with 'v'.\"\nconst Line2Marker = \"Selected text can then be \".length\nconst Line2Marker2 = \"Selected text can then be (y)anked, (c)hanged, or (d)elete\".length\nconst Line4Marker = \"Selected lines can also be\".length\nconst Line4PostPaste =\n    \"Selected lines can also be (y)anked, (c)hanged, or (d)eleted with a single keypress\"\nconst Line3Marker = \"To select entire lines, use 'V' to include \".length\nconst Line3Marker2 = \"To select entire lines, use 'V' to include line-endin\".length\nconst Line3Pending = \"To select entire lines, use 'V' to include  characters.\"\nconst Line3Change = \"To select entire lines, use 'V' to include newline characters.\"\nconst Line3Marker3 = \"To select entire lines, use 'V' to include newlin\".length\n\nexport class VisualModeTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1, Line2, Line3, Line4]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 0, Line1Marker),\n            new Stages.WaitForModeStage(\"Change to Visual mode with 'v'\", \"visual\"),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 0, Line1Marker2),\n            new Stages.WaitForStateStage(\"Hit 'd' to delete the selected text\", [\n                Line1Change,\n                Line2,\n                Line3,\n                Line4,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, Line2Marker),\n            new Stages.WaitForModeStage(\"Change to Visual mode with 'v'\", \"visual\"),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 1, Line2Marker2),\n            new Stages.WaitForRegisterStage(\n                \"Yank the selection with 'y'\",\n                \"(y)anked, (c)hanged, or (d)eleted\",\n            ),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 3, Line4Marker),\n            new Stages.WaitForStateStage(\"Paste the yanked text with 'p'\", [\n                Line1Change,\n                Line2,\n                Line3,\n                Line4PostPaste,\n            ]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 2, Line3Marker),\n            new Stages.WaitForModeStage(\"Change to Visual mode with 'v'\", \"visual\"),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 2, Line3Marker2),\n            new Stages.WaitForStateStage(\"Change the selected text with 'c'\", [\n                Line1Change,\n                Line2,\n                Line3Pending,\n                Line4PostPaste,\n            ]),\n            new Stages.WaitForStateStage(\"Enter the word 'newline'\", [\n                Line1Change,\n                Line2,\n                Line3Change,\n                Line4PostPaste,\n            ]),\n            new Stages.WaitForModeStage(\"Exit Insert mode by hitting <esc>\", \"normal\"),\n            new Stages.WaitForModeStage(\"Move into Visual Line mode with 'V'\", \"visual\"),\n            new Stages.MoveToGoalStage(\"Move to the next line\", 3, Line3Marker3),\n            new Stages.WaitForStateStage(\"Delete the selected lines with 'd'\", [\n                Line1Change,\n                Line2,\n            ]),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.visual_mode\",\n            name: \"Visual Select: v, V\",\n            description:\n                \"Sometimes the text you want to modify isn't on a simple word boundary.  We often need to change, yank, or delete any arbitrary text.  Rather than performing a cursor movement and hoping you affected the correct characters, you can visually select text.  Using 'v' will select characters as you move, and 'V' will select lines\",\n            level: 230,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.HJKLKeys />,\n            <Notes.WordKey />,\n            <Notes.BeginningKey />,\n            <Notes.EndKey />,\n            <Notes.VisualModeKey />,\n            <Notes.VisualLineModeKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/WordMotionTutorial.tsx",
    "content": "/**\n * WordMotionTutorial.tsx\n *\n * Tutorial that exercises basic word motion - `w`, `b`, `e`\n */\n\nimport * as React from \"react\"\n\nimport { ITutorial, ITutorialMetadata, ITutorialStage } from \"./../ITutorial\"\nimport * as Notes from \"./../Notes\"\nimport * as Stages from \"./../Stages\"\n\nconst Line1 = \"Use the w key to move to the BEGINNING of the NEXT word.\"\nconst Line2 = \"Use the e key to move to the END of the NEXT word.\"\nconst Line3 = \"Use the b key to move to the BEGINNING of the PREVIOUS word.\"\nconst Empty = \"\"\nconst Line4 = \"Word boundaries are defined by characters like '\\\"[]().:\"\nconst Line5 = \"Use the W, E, B keys to use WHITESPACE as the only word boundary\"\nconst Line6 = \"Try moving over an IP address like 192.168.100.252 to see the behavior\"\nconst Line7 = \"Move past this timestamp [1970-01-01_00:00:00,000] with a single key press\"\n\nexport class WordMotionTutorial implements ITutorial {\n    private _stages: ITutorialStage[]\n\n    constructor() {\n        this._stages = [\n            new Stages.SetBufferStage([Line1]),\n            new Stages.SetCursorPositionStage(0, 0),\n            new Stages.MoveToGoalStage(\"Use the `w` key to move to the 't' character\", 0, 4),\n            new Stages.MoveToGoalStage(\"Use the `w` key to move to the next word\", 0, 8),\n            new Stages.MoveToGoalStage(\"Use the `w` key to move to the 'key' word\", 0, 10),\n            new Stages.SetBufferStage([Line1, Line2]),\n            new Stages.MoveToGoalStage(\"Use the 'j' key to move down a line\", 1, 10),\n            new Stages.MoveToGoalStage(\n                \"Use the 'e' key to move to the end of the current word\",\n                1,\n                12,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use the 'e' key to move to the end of the next word\",\n                1,\n                15,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use the 'e' key to move to the end of the next word\",\n                1,\n                20,\n            ),\n            new Stages.SetBufferStage([Line1, Line2, Line3]),\n            new Stages.MoveToGoalStage(\"Use the 'j' key to move down a line\", 2, 20),\n            new Stages.MoveToGoalStage(\n                \"Use the 'b' key to move to the beginning of the current word\",\n                2,\n                17,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use the 'b' key to move to the beginning of the previous word\",\n                2,\n                14,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use the 'b' key to move to the beginning of the previous word\",\n                2,\n                10,\n            ),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Empty, Line4, Line5, Line6]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 6, 35),\n            new Stages.MoveToGoalStage(\n                \"Keep hitting 'w' until you move past the IP address\",\n                6,\n                51,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Well that was annoying.  Now use 'B' to jump backwards by whitespace\",\n                6,\n                35,\n            ),\n            new Stages.MoveToGoalStage(\n                \"Use 'W' to jump to the next word by whitespace.  Much faster!\",\n                6,\n                51,\n            ),\n            new Stages.SetBufferStage([Line1, Line2, Line3, Empty, Line4, Line5, Line6, Line7]),\n            new Stages.MoveToGoalStage(\"Move to the goal marker\", 7, 25),\n            new Stages.MoveToGoalStage(\"Use 'W' to move to the word after the timestamp\", 7, 51),\n            new Stages.MoveToGoalStage(\"Use 'B' to move to the beginning of the timestamp\", 7, 25),\n            new Stages.MoveToGoalStage(\"Use 'E' to move to the end of the timestamp\", 7, 49),\n        ]\n    }\n\n    public get metadata(): ITutorialMetadata {\n        return {\n            id: \"oni.tutorials.word_motion\",\n            name: \"Word Motion: w, e, b\",\n            description:\n                \"Often, `h` and `l` aren't the fastest way to move in a line. Word motions can be useful here - and even more useful when coupled with operators (we'll explore those later)! The `w` key moves to the first letter of the next word, the `e` key moves to the end of the next word, and the `b` key moves to the beginning letter of the previous word.\",\n            level: 130,\n        }\n    }\n\n    public get stages(): ITutorialStage[] {\n        return this._stages\n    }\n\n    public get notes(): JSX.Element[] {\n        return [\n            <Notes.HJKLKeys />,\n            <Notes.WordKey />,\n            <Notes.EndKey />,\n            <Notes.BeginningKey />,\n            <Notes.BigWordKey />,\n            <Notes.BigEndKey />,\n            <Notes.BigBeginningKey />,\n        ]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/Tutorials/index.tsx",
    "content": "/**\n * TutorialManager\n */\n\nimport { ITutorial } from \"./../ITutorial\"\n\nimport { BasicMovementTutorial } from \"./BasicMovementTutorial\"\nimport { BeginningsAndEndingsTutorial } from \"./BeginningsAndEndingsTutorial\"\nimport { ChangeOperatorTutorial } from \"./ChangeOperatorTutorial\"\nimport { CopyPasteTutorial } from \"./CopyPasteTutorial\"\nimport { DeleteCharacterTutorial } from \"./DeleteCharacterTutorial\"\nimport { DeleteOperatorTutorial } from \"./DeleteOperatorTutorial\"\nimport { DotCommandTutorial } from \"./DotCommandTutorial\"\nimport { InlineFindingTutorial } from \"./InlineFindingTutorial\"\nimport { InsertAndUndoTutorial } from \"./InsertAndUndoTutorial\"\nimport { SearchInBufferTutorial } from \"./SearchInBufferTutorial\"\nimport { SwitchModeTutorial } from \"./SwitchModeTutorial\"\nimport { TargetsVimPluginTutorial } from \"./TargetsVimPluginTutorial\"\nimport { TextObjectsTutorial } from \"./TextObjectsTutorial\"\nimport { VerticalMovementTutorial } from \"./VerticalMovementTutorial\"\nimport { VisualModeTutorial } from \"./VisualModeTutorial\"\nimport { WordMotionTutorial } from \"./WordMotionTutorial\"\n\nexport * from \"./DeleteCharacterTutorial\"\nexport * from \"./SwitchModeTutorial\"\n\nexport const AllTutorials: ITutorial[] = [\n    new BeginningsAndEndingsTutorial(),\n    new SwitchModeTutorial(),\n    new BasicMovementTutorial(),\n    new DeleteCharacterTutorial(),\n    new DeleteOperatorTutorial(),\n    new InsertAndUndoTutorial(),\n    new VerticalMovementTutorial(),\n    new WordMotionTutorial(),\n    new SearchInBufferTutorial(),\n    new CopyPasteTutorial(),\n    new ChangeOperatorTutorial(),\n    new VisualModeTutorial(),\n    new TargetsVimPluginTutorial(),\n    new InlineFindingTutorial(),\n    new TextObjectsTutorial(),\n    new DotCommandTutorial(),\n]\n"
  },
  {
    "path": "browser/src/Services/Learning/Tutorial/index.ts",
    "content": "export * from \"./ITutorial\"\nexport * from \"./TutorialManager\"\nexport * from \"./Tutorials\"\n"
  },
  {
    "path": "browser/src/Services/Learning/index.ts",
    "content": "/**\n * Learning.ts\n */\n\nimport { getPersistentStore, IPersistentStore } from \"./../../PersistentStore\"\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { OverlayManager } from \"./../Overlay\"\nimport { SidebarManager } from \"./../Sidebar\"\nimport { WindowManager } from \"./../WindowManager\"\n\nimport { LearningPane } from \"./LearningPane\"\nimport { IPersistedTutorialState, TutorialManager } from \"./Tutorial/TutorialManager\"\n\nimport * as Achievements from \"./Achievements\"\nimport { ITutorial } from \"./Tutorial/ITutorial\"\nimport { AllTutorials } from \"./Tutorial/Tutorials\"\n\nlet _tutorialManager: TutorialManager\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n    overlayManager: OverlayManager,\n    sidebarManager: SidebarManager,\n    windowManager: WindowManager,\n) => {\n    const learningEnabled = configuration.getValue(\"learning.enabled\")\n\n    Achievements.activate(\n        commandManager,\n        configuration,\n        editorManager,\n        sidebarManager,\n        overlayManager,\n    )\n\n    const achievements = Achievements.getInstance()\n\n    if (!learningEnabled) {\n        return\n    }\n\n    const store: IPersistentStore<IPersistedTutorialState> = getPersistentStore(\"oni-tutorial\", {\n        completionInfo: {},\n    })\n    _tutorialManager = new TutorialManager(editorManager, store, windowManager)\n    _tutorialManager.start()\n    sidebarManager.add(\"trophy\", new LearningPane(_tutorialManager, commandManager))\n\n    _tutorialManager.onTutorialCompletedEvent.subscribe(() => {\n        achievements.notifyGoal(\"oni.achievement.tutorial.complete\")\n    })\n\n    achievements.registerAchievement({\n        uniqueId: \"oni.achievement.padawan\",\n        name: \"Padawan\",\n        description: \"Complete a level in the interactive tutorial\",\n        goals: [\n            {\n                name: null,\n                goalId: \"oni.achievement.tutorial.complete\",\n                count: 1,\n            },\n        ],\n    })\n\n    AllTutorials.forEach((tut: ITutorial) => _tutorialManager.registerTutorial(tut))\n\n    commandManager.registerCommand({\n        command: \"experimental.tutorial.start\",\n        name: null,\n        detail: null,\n        execute: () => _tutorialManager.startTutorial(null),\n    })\n}\n\nexport const getTutorialManagerInstance = () => _tutorialManager\n"
  },
  {
    "path": "browser/src/Services/Menu/Filter/FuseFilter.ts",
    "content": "import * as Fuse from \"fuse.js\"\nimport * as sortBy from \"lodash/sortBy\"\n\nimport * as utils from \"./Utils\"\n\nimport { IMenuOptionWithHighlights } from \"./../Menu\"\n\nexport function filter(options: any[], searchString: string): IMenuOptionWithHighlights[] {\n    if (!searchString) {\n        const opt = options.map(o => {\n            return {\n                ...o,\n                label: o.label,\n                detail: o.detail,\n                icon: o.icon,\n                pinned: o.pinned,\n                metadata: o.metadata,\n                detailHighlights: [],\n                labelHighlights: [],\n                additionalComponent: o.additionalComponent,\n            }\n        })\n\n        return sortBy(opt, o => (o.pinned ? 0 : 1))\n    }\n\n    const fuseOptions = {\n        keys: [\n            {\n                name: \"label\",\n                weight: 0.6,\n            },\n            {\n                name: \"detail\",\n                weight: 0.4,\n            },\n        ],\n        caseSensitive: utils.shouldBeCaseSensitive(searchString),\n        include: [\"matches\"],\n    }\n\n    // remove duplicate characters\n    const searchSet = new Set(searchString)\n\n    // remove any items that don't have all the characters from searchString\n    // For this first pass, ignore case\n    const filteredOptions = options.filter(o => {\n        if (!o.label && !o.detail) {\n            return false\n        }\n\n        const label = o.label ? o.label.toLowerCase() : \"\"\n        const detail = o.detail ? o.detail.toLowerCase() : \"\"\n\n        const combined = label + detail\n\n        for (const c of searchSet) {\n            if (combined.indexOf(c.toLowerCase()) === -1) {\n                return false\n            }\n        }\n\n        return true\n    })\n\n    const fuse = new Fuse(filteredOptions, fuseOptions)\n    const results = fuse.search(searchString)\n\n    const highlightOptions = results.map((f: any) => {\n        let labelHighlights: number[][] = []\n        let detailHighlights: number[][] = []\n        // matches will have 1 or 2 items depending on\n        // whether one or both (label and detail) matched\n        f.matches.forEach((obj: any) => {\n            if (obj.key === \"label\") {\n                labelHighlights = obj.indices\n            } else {\n                detailHighlights = obj.indices\n            }\n        })\n\n        return {\n            ...f,\n            icon: f.item.icon,\n            pinned: f.item.pinned,\n            label: f.item.label,\n            detail: f.item.detail,\n            metadata: f.item.metadata,\n            labelHighlights: convertArrayOfPairsToIndices(labelHighlights),\n            detailHighlights: convertArrayOfPairsToIndices(detailHighlights),\n            additionalComponent: f.item.additionalComponent,\n        }\n    })\n\n    return highlightOptions\n}\n\nfunction convertArrayOfPairsToIndices(pairs: number[][]): number[] {\n    const ret: number[] = []\n\n    pairs.forEach(p => {\n        const [startIndex, endIndex] = p\n\n        for (let i = startIndex; i <= endIndex; i++) {\n            ret.push(i)\n        }\n    })\n\n    return ret\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Filter/NoFilter.ts",
    "content": "// import * as Oni from \"oni-api\" // TODO: add additionalComponent to Oni.Menu.MenuOption (as optional?)\n// TODO: Also might want to merge IMenuOptionWithHighlights as optional fields\n\nimport { IMenuOptionWithHighlights } from \"../Menu\"\n\nfunction convert(entry: any /*Oni.Menu.MenuOption*/): IMenuOptionWithHighlights {\n    return {\n        ...entry,\n        label: entry.label,\n        detail: entry.detail,\n        icon: entry.icon,\n        pinned: entry.pinned,\n        metadata: entry.metadata,\n        detailHighlights: [],\n        labelHighlights: [],\n        additionalComponent: entry.additionalComponent,\n    }\n}\n\nexport function filter(options: any[], searchString: string): IMenuOptionWithHighlights[] {\n    return options.map(o => convert(o))\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Filter/RegExFilter.ts",
    "content": "import * as sortBy from \"lodash/sortBy\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as utils from \"./Utils\"\n\nimport { IMenuOptionWithHighlights } from \"./../Menu\"\n\nimport {\n    createLetterCountDictionary,\n    LetterCountDictionary,\n} from \"./../../../UI/components/HighlightText\"\n\nexport function filter(\n    options: Oni.Menu.MenuOption[],\n    searchString: string,\n): IMenuOptionWithHighlights[] {\n    if (!searchString) {\n        const opt = options.map(o => {\n            return {\n                ...o,\n                detailHighlights: [],\n                labelHighlights: [],\n            }\n        })\n\n        return sortBy(opt, o => (o.pinned ? 0 : 1))\n    }\n\n    const isCaseSensitive = utils.shouldBeCaseSensitive(searchString)\n\n    if (!isCaseSensitive) {\n        searchString = searchString.toLowerCase()\n    }\n\n    const listOfSearchTerms = searchString.split(\" \").filter(x => x)\n\n    let filteredOptions = options\n\n    listOfSearchTerms.map(searchTerm => {\n        filteredOptions = processSearchTerm(searchTerm, filteredOptions, isCaseSensitive)\n    })\n\n    const ret = filteredOptions.map(fo => {\n        const letterCountDictionary = createLetterCountDictionary(searchString)\n\n        const detailHighlights = getHighlightsFromString(\n            fo.detail,\n            letterCountDictionary,\n            isCaseSensitive,\n        )\n        const labelHighlights = getHighlightsFromString(\n            fo.label,\n            letterCountDictionary,\n            isCaseSensitive,\n        )\n\n        return {\n            ...fo,\n            detailHighlights,\n            labelHighlights,\n        }\n    })\n\n    return ret\n}\n\nexport function processSearchTerm(\n    searchString: string,\n    options: Oni.Menu.MenuOption[],\n    isCaseSensitive: boolean,\n): Oni.Menu.MenuOption[] {\n    const filterRegExp = new RegExp(\".*\" + searchString.split(\"\").join(\".*\") + \".*\")\n\n    return options.filter(f => {\n        let textToFilterOn = f.detail + f.label\n\n        if (!isCaseSensitive) {\n            textToFilterOn = textToFilterOn.toLowerCase()\n        }\n\n        return textToFilterOn.match(filterRegExp)\n    })\n}\n\nexport function getHighlightsFromString(\n    text: string,\n    letterCountDictionary: LetterCountDictionary,\n    isCaseSensitive: boolean = false,\n): number[] {\n    if (!text) {\n        return []\n    }\n\n    const ret: number[] = []\n\n    for (let i = 0; i < text.length; i++) {\n        const letter = isCaseSensitive ? text[i] : text[i].toLowerCase()\n        const idx = i\n        if (letterCountDictionary[letter] && letterCountDictionary[letter] > 0) {\n            ret.push(idx)\n            letterCountDictionary[letter]--\n        }\n    }\n\n    return ret\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Filter/Utils.ts",
    "content": "import { configuration } from \"./../../../Services/Configuration\"\n\nexport const shouldBeCaseSensitive = (searchString: string): boolean => {\n    // TODO: Technically, this makes the reducer 'impure',\n    // which is not ideal - need to refactor eventually.\n    //\n    // One option is to plumb through the configuration setting\n    // from the top-level, but it might be worth extracting\n    // out the filter strategy in general.\n    const caseSensitivitySetting = configuration.getValue(\"menu.caseSensitive\")\n\n    if (caseSensitivitySetting === false) {\n        return false\n    } else if (caseSensitivitySetting === true) {\n        return true\n    } else {\n        // \"Smart\" casing strategy\n        // If the string is all lower-case, not case sensitive..\n        if (searchString === searchString.toLowerCase()) {\n            return false\n            // Otherwise, it is case sensitive..\n        } else {\n            return true\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Filter/VSCodeFilter.ts",
    "content": "import * as sortBy from \"lodash/sortBy\"\n\nimport * as Oni from \"oni-api\"\n\nimport {\n    compareItemsByScoreOni,\n    getHighlightsFromResult,\n    scoreItemOni,\n} from \"./../../Search/Scorer/OniQuickOpenScorer\"\nimport { ScorerCache } from \"./../../Search/Scorer/QuickOpenScorer\"\n\nimport * as utils from \"./Utils\"\n\nimport { IMenuOptionWithHighlights } from \"./../Menu\"\n\nexport function filter(\n    options: Oni.Menu.MenuOption[],\n    searchString: string,\n): IMenuOptionWithHighlights[] {\n    if (!searchString) {\n        const opt = options.map(o => {\n            return {\n                ...o,\n                detailHighlights: [],\n                labelHighlights: [],\n            }\n        })\n\n        return sortBy(opt, o => (o.pinned ? 0 : 1))\n    }\n\n    const isCaseSensitive = utils.shouldBeCaseSensitive(searchString)\n\n    if (!isCaseSensitive) {\n        searchString = searchString.toLowerCase()\n    }\n\n    const listOfSearchTerms = searchString.split(\" \").filter(x => x)\n\n    // Since the VSCode scorer doesn't deal so well with the spaces,\n    // instead rebuild the term in reverse order.\n    // ie `index browser editor` becomes `browsereditorindex`\n    // This allows the scoring and highlighting to work better.\n    const vsCodeSearchString =\n        listOfSearchTerms.length > 1\n            ? listOfSearchTerms.slice(1).join(\"\") + listOfSearchTerms[0]\n            : listOfSearchTerms[0]\n\n    // Adds a cache for the scores. This is needed to stop the final score\n    // compare from repeating all the scoring logic again.\n    // Currently, this only persists for the current search, which will speed\n    // up that search only.\n    // TODO: Is it worth instead persisting this cache?\n    // Plus side is repeated searches are fast.\n    // Down side is there will be a lot of rubbish being stored too.\n    const cache: ScorerCache = {}\n\n    const filteredOptions = processSearchTerm(vsCodeSearchString, options, cache)\n\n    const ret = filteredOptions.filter(fo => {\n        if (fo.score === 0) {\n            return false\n        } else {\n            return true\n        }\n    })\n\n    return ret.sort((e1, e2) => compareItemsByScoreOni(e1, e2, vsCodeSearchString, true, cache))\n}\n\nexport function processSearchTerm(\n    searchString: string,\n    options: Oni.Menu.MenuOption[],\n    cache: ScorerCache,\n): Oni.Menu.IMenuOptionWithHighlights[] {\n    const result: Oni.Menu.IMenuOptionWithHighlights[] = options.map(f => {\n        const itemScore = scoreItemOni(f, searchString, true, cache)\n        const detailHighlights = getHighlightsFromResult(itemScore.descriptionMatch)\n        const labelHighlights = getHighlightsFromResult(itemScore.labelMatch)\n\n        return {\n            ...f,\n            detailHighlights,\n            labelHighlights,\n            score: f.pinned ? Number.MAX_SAFE_INTEGER : itemScore.score,\n        }\n    })\n\n    return result\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Filter/index.ts",
    "content": "import * as Oni from \"oni-api\"\n\nimport { filter as fuseFilter } from \"./FuseFilter\"\nimport { filter as noFilter } from \"./NoFilter\"\nimport { filter as RegExFilter } from \"./RegExFilter\"\nimport { filter as vscodeFilter } from \"./VSCodeFilter\"\n\nclass Filters implements Oni.Menu.IMenuFilters {\n    private _filters = new Map<string, Oni.Menu.IMenuFilter>()\n\n    constructor() {\n        this._filters\n            .set(\"default\", noFilter)\n            .set(\"none\", noFilter)\n            .set(\"fuse\", fuseFilter)\n            .set(\"regex\", RegExFilter)\n            .set(\"vscode\", vscodeFilter)\n    }\n\n    public getDefault(): Oni.Menu.IMenuFilter {\n        return this.getByName(\"default\")\n    }\n\n    public getByName(name: string): Oni.Menu.IMenuFilter {\n        return this._filters.has(name) ? this._filters.get(name) : this.getDefault()\n    }\n\n    // TODO: Add register & unregister for plugins\n}\n\nconst _instance = new Filters()\n\nexport function getInstance(owner: string): Oni.Menu.IMenuFilters {\n    return _instance\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Menu.less",
    "content": "@import (reference) \"./../../UI/components/common.less\";\n\n@keyframes fade-in-and-down {\n    from {\n        opacity: 0;\n    }\n    to {\n        opacity: 1;\n    }\n}\n\n.tool-tip-container {\n    .box-shadow;\n}\n\n.menu-background {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    bottom: 0px;\n    right: 0px;\n    background-color: rgba(0, 0, 0, 0.25);\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n}\n\n.menu {\n    .box-shadow;\n\n    position: relative;\n    margin-top: 16px;\n    padding: 8px;\n    width: 75%;\n    max-width: 900px;\n\n    input {\n        border: 0px;\n        background-color: rgba(0, 0, 0, 0.2);\n        font-size: 1.1em;\n        box-sizing: border-box;\n        width: 100%;\n        padding: 8px;\n        outline: none;\n    }\n\n    .items {\n        .item {\n            .fa:not(.fa-spin) {\n                padding-left: 4px;\n                padding-right: 4px;\n            }\n\n            &:hover {\n                background-color: rgba(0, 0, 0, 0.1);\n            }\n            &.selected {\n                background-color: rgba(0, 0, 0, 0.1);\n            }\n\n            .label {\n                margin: 4px;\n                padding-right: 8px;\n            }\n\n            .detail {\n                font-size: @font-size-small;\n                color: @text-color-detail;\n                flex: 1 1 auto;\n                overflow: hidden;\n                text-overflow: ellipsis;\n                padding-right: 8px;\n            }\n        }\n    }\n\n    .footer {\n        .box-shadow;\n\n        text-align: center;\n        width: 100%;\n        transition-property: transform, opacity;\n        transition-duration: 0.5s;\n        position: absolute;\n        bottom: 0px;\n        height: 3em;\n        margin-left: -8px;\n\n        // Put behind items / menu element\n        z-index: -1;\n\n        &.loading {\n            transform: translateY(100%);\n            opacity: 1;\n\n            .loading-spinner {\n                opacity: 1;\n            }\n        }\n\n        &.loaded {\n            opacity: 0;\n            transform: translateY(0%);\n        }\n\n        .loading-spinner {\n            line-height: 3em;\n            height: 3em;\n\n            opacity: 0;\n\n            .loading & {\n                opacity: 1;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/Menu.ts",
    "content": "/**\n * Menu.ts\n *\n * Implements API surface area for working with the status bar\n */\n\nimport { bindActionCreators } from \"redux\"\nimport thunk from \"redux-thunk\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { filter as fuseFilter } from \"./Filter/FuseFilter\"\nimport * as ActionCreators from \"./MenuActionCreators\"\nimport { MenuContainer } from \"./MenuComponent\"\nimport { createReducer } from \"./MenuReducer\"\nimport * as State from \"./MenuState\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { Overlay, OverlayManager } from \"./../Overlay\"\n\nimport { createStore } from \"./../../Redux\"\n\nexport interface IMenuOptionWithHighlights extends Oni.Menu.MenuOption {\n    labelHighlights: number[]\n    detailHighlights: number[]\n}\n\nexport type MenuState = State.IMenus<Oni.Menu.MenuOption, IMenuOptionWithHighlights>\n\nconst reducer = createReducer<Oni.Menu.MenuOption, IMenuOptionWithHighlights>()\n\nexport const menuStore = createStore<MenuState>(\n    \"MenuStore\",\n    reducer,\n    State.createDefaultState<Oni.Menu.MenuOption, IMenuOptionWithHighlights>(),\n    [thunk],\n)\n\nexport const menuActions: typeof ActionCreators = bindActionCreators(\n    ActionCreators as any,\n    menuStore.dispatch,\n)\n\nexport const sanitizeConfigurationValue = (value: any, defaultValue: number): number => {\n    const parsedValue = parseInt(value, 10)\n    return parsedValue > 0 ? parsedValue : defaultValue\n}\n\nexport class MenuManager {\n    private _id: number = 0\n    private _overlay: Overlay\n\n    constructor(private _configuration: Configuration, private _overlayManager: OverlayManager) {\n        this._overlay = this._overlayManager.createItem()\n        this._overlay.setContents(MenuContainer())\n        this._overlay.show()\n\n        this._configuration.onConfigurationChanged.subscribe(() => {\n            this._updateConfiguration()\n        })\n\n        this._updateConfiguration()\n    }\n\n    public create(): Menu {\n        this._id++\n        return new Menu(this._id.toString())\n    }\n\n    public isMenuOpen(): boolean {\n        return !!menuStore.getState().menu\n    }\n\n    public nextMenuItem(): void {\n        menuActions.nextMenuItem()\n    }\n\n    public previousMenuItem(): void {\n        menuActions.previousMenuItem()\n    }\n\n    public closeActiveMenu(): void {\n        menuActions.hidePopupMenu()\n    }\n\n    public selectMenuItem(idx?: number): void {\n        const menuState = menuStore.getState()\n\n        if (menuState && menuState.menu) {\n            menuState.menu.onSelectItem(idx)\n        }\n    }\n\n    private _updateConfiguration(): void {\n        const values = this._configuration.getValues()\n        const rowHeightUnsanitized = values[\"menu.rowHeight\"]\n        const maxItemsUnsanitized = values[\"menu.maxItemsToShow\"]\n\n        menuActions.setMenuConfiguration(\n            sanitizeConfigurationValue(rowHeightUnsanitized, 40),\n            sanitizeConfigurationValue(maxItemsUnsanitized, 6),\n        )\n    }\n}\n\nexport class Menu implements Oni.Menu.MenuInstance {\n    private _onItemSelected = new Event<any>()\n    private _onSelectedItemChanged = new Event<Oni.Menu.MenuOption>()\n    private _onFilterTextChanged = new Event<string>()\n    private _onHide = new Event<void>()\n    private _filterFunction = fuseFilter\n\n    public get onHide(): IEvent<void> {\n        return this._onHide\n    }\n\n    public get onItemSelected(): IEvent<any> {\n        return this._onItemSelected\n    }\n\n    public get onSelectedItemChanged(): IEvent<Oni.Menu.MenuOption> {\n        return this._onSelectedItemChanged\n    }\n\n    public get onFilterTextChanged(): IEvent<string> {\n        return this._onFilterTextChanged\n    }\n\n    public get selectedItem() {\n        return this._getSelectedItem()\n    }\n\n    constructor(private _id: string) {}\n\n    public isOpen(): boolean {\n        const menuState = menuStore.getState()\n        return menuState.menu && menuState.menu.id === this._id\n    }\n\n    public setLoading(isLoading: boolean): void {\n        menuActions.setMenuLoading(this._id, isLoading)\n    }\n\n    public setItems(items: Oni.Menu.MenuOption[]): void {\n        menuActions.setMenuItems(this._id, items)\n    }\n\n    public setFilterFunction(\n        filterFunc: (\n            items: Oni.Menu.MenuOption[],\n            searchString: string,\n        ) => IMenuOptionWithHighlights[],\n    ) {\n        this._filterFunction = filterFunc\n    }\n\n    public show(): void {\n        menuActions.showPopupMenu(this._id, {\n            filterFunction: this._filterFunction,\n            onSelectedItemChanged: item => this._onSelectedItemChanged.dispatch(item),\n            onSelectItem: (idx: number) => this._onItemSelectedHandler(idx),\n            onHide: () => this._onHide.dispatch(),\n            onFilterTextChanged: newText => this._onFilterTextChanged.dispatch(newText),\n        })\n    }\n\n    public hide(): void {\n        menuActions.hidePopupMenu()\n    }\n\n    private _onItemSelectedHandler(idx?: number): void {\n        const selectedOption = this._getSelectedItem(idx)\n        this._onItemSelected.dispatch(selectedOption)\n\n        this.hide()\n    }\n\n    private _getSelectedItem(idx?: number) {\n        const menuState = menuStore.getState()\n\n        if (!menuState.menu) {\n            return null\n        }\n\n        const index = typeof idx === \"number\" ? idx : menuState.menu.selectedIndex\n\n        return menuState.menu.filteredOptions[index]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/MenuActionCreators.ts",
    "content": "/**\n * MenuActionCreators.ts\n */\n\nimport * as MenuActions from \"./MenuActions\"\n\n// Selector\nconst getSelectedItem = (contextMenuState: any) => {\n    if (!contextMenuState.menu) {\n        return null\n    }\n\n    const index = contextMenuState.menu.selectedIndex\n\n    return contextMenuState.menu.filteredOptions[index]\n}\n\nconst notifySelectedItemChange = (contextMenuState: any) => {\n    const selectedItem = getSelectedItem(contextMenuState)\n\n    if (contextMenuState && contextMenuState.menu && contextMenuState.menu.onSelectedItemChanged) {\n        contextMenuState.menu.onSelectedItemChanged(selectedItem)\n    }\n}\n\nexport const setMenuConfiguration = (rowHeight: number, maxItemsToShow: number) => {\n    return {\n        type: \"SET_MENU_CONFIGURATION\",\n        payload: {\n            rowHeight,\n            maxItemsToShow,\n        },\n    }\n}\n\nexport const showPopupMenu = (\n    id: string,\n    opts?: MenuActions.IMenuOptions,\n    items?: any,\n    filter?: string,\n) => {\n    return {\n        type: \"SHOW_MENU\",\n        payload: {\n            id,\n            items,\n            filter,\n            options: opts,\n        },\n    }\n}\n\nexport const setMenuLoading = (id: string, isLoading: boolean) => ({\n    type: \"SET_MENU_LOADING\",\n    payload: {\n        id,\n        isLoading,\n    },\n})\n\nexport const setMenuItems = (id: string, items: any[]) => ({\n    type: \"SET_MENU_ITEMS\",\n    payload: {\n        id,\n        items,\n    },\n})\n\nexport const hidePopupMenu = () => (dispatch: any, getState: any) => {\n    const state = getState()\n\n    if (!state.menu) {\n        return\n    }\n\n    if (state.menu.onHide) {\n        state.menu.onHide()\n    }\n\n    dispatch({\n        type: \"HIDE_MENU\",\n    })\n}\n\nexport const previousMenuItem = () => (dispatch: any, getState: any) => {\n    dispatch({\n        type: \"PREVIOUS_MENU\",\n    })\n\n    notifySelectedItemChange(getState())\n}\n\nexport const filterMenu = (filterString: string) => (dispatch: any, getState: any) => {\n    const state = getState()\n\n    if (!state.menu) {\n        return\n    }\n\n    if (state.menu.onFilterTextChanged) {\n        state.menu.onFilterTextChanged(filterString)\n    }\n\n    dispatch({\n        type: \"FILTER_MENU\",\n        payload: {\n            filter: filterString,\n        },\n    })\n\n    notifySelectedItemChange(getState())\n}\n\nexport const nextMenuItem = () => (dispatch: any, getState: any) => {\n    dispatch({\n        type: \"NEXT_MENU\",\n    })\n\n    notifySelectedItemChange(getState())\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/MenuActions.ts",
    "content": "/**\n * Menu.ts\n *\n * Implements API surface area for working with the status bar\n */\n\nexport interface IMenuOptions {\n    foregroundColor?: string\n    backgroundColor?: string\n    highlightColor?: string\n    filterFunction?: (items: any[], searchString: string) => any[]\n    onSelectedItemChanged?: (newItem: any) => void\n    onSelectItem?: (idx: number) => void\n    onHide?: () => void\n    onFilterTextChanged?: (newText: string) => void\n}\n\nexport interface ISetConfigurationMenuAction {\n    type: \"SET_MENU_CONFIGURATION\"\n    payload: {\n        rowHeight: number\n        maxItemsToShow: number\n    }\n}\n\nexport interface IShowMenuAction {\n    type: \"SHOW_MENU\"\n    payload: {\n        id: string\n        options?: IMenuOptions\n        items?: any[]\n        filter?: string\n    }\n}\n\nexport interface ISetMenuItems<T> {\n    type: \"SET_MENU_ITEMS\"\n    payload: {\n        id: string\n        items: T[]\n    }\n}\n\nexport interface ISetMenuLoading {\n    type: \"SET_MENU_LOADING\"\n    payload: {\n        id: string\n        isLoading: boolean\n    }\n}\n\nexport interface IFilterMenuAction {\n    type: \"FILTER_MENU\"\n    payload: {\n        id: string\n        filter: string\n    }\n}\n\nexport interface IHideMenuAction {\n    type: \"HIDE_MENU\"\n}\n\nexport interface INextMenuAction {\n    type: \"NEXT_MENU\"\n}\n\nexport interface IPreviousMenuAction {\n    type: \"PREVIOUS_MENU\"\n}\n\nexport type MenuAction =\n    | IShowMenuAction\n    | ISetConfigurationMenuAction\n    | ISetMenuLoading\n    | ISetMenuItems<any>\n    | IFilterMenuAction\n    | IHideMenuAction\n    | INextMenuAction\n    | IPreviousMenuAction\n"
  },
  {
    "path": "browser/src/Services/Menu/MenuComponent.tsx",
    "content": "import * as React from \"react\"\nimport * as ReactDOM from \"react-dom\"\nimport { connect, Provider } from \"react-redux\"\n\nimport { AutoSizer, List } from \"react-virtualized\"\n\nimport * as Oni from \"oni-api\"\n\nimport styled, { getSelectedBorder } from \"../../UI/components/common\"\nimport { HighlightTextByIndex } from \"./../../UI/components/HighlightText\"\nimport { Icon, IconSize } from \"./../../UI/Icon\"\n\nimport { focusManager } from \"./../FocusManager\"\n\nimport { IMenuOptionWithHighlights, menuStore } from \"./Menu\"\nimport * as ActionCreators from \"./MenuActionCreators\"\nimport * as State from \"./MenuState\"\nimport { render as renderPinnedIcon } from \"./PinnedIconView\"\n\nimport { withProps } from \"./../../UI/components/common\"\n\nimport { TextInputView } from \"./../../UI/components/LightweightText\"\n\nexport interface IMenuProps {\n    visible: boolean\n    selectedIndex: number\n    filterText: string\n    onChangeFilterText: (text: string) => void\n    onSelect: (selectedIndex?: number) => void\n    onHide: () => void\n    items: IMenuOptionWithHighlights[]\n    isLoading: boolean\n\n    rowHeight: number\n    maxItemsToShow: number\n}\n\nconst MenuStyleWrapper = styled.div`\n    background-color: ${props => props.theme[\"menu.background\"]};\n    color: ${props => props.theme[\"menu.foreground\"]};\n\n    & input {\n        color: ${props => props.theme[\"menu.foreground\"]};\n        background-color: rgba(0, 0, 0.2);\n    }\n`\n\nexport class MenuView extends React.PureComponent<IMenuProps, {}> {\n    private _inputElement: HTMLInputElement = null\n    private _popupBody: Element = null\n\n    public componentWillUpdate(newProps: Readonly<IMenuProps>): void {\n        if (newProps.visible !== this.props.visible && !newProps.visible && this._inputElement) {\n            focusManager.popFocus(this._inputElement)\n        }\n    }\n\n    public render(): null | JSX.Element {\n        if (!this.props.visible) {\n            return null\n        }\n\n        const rowRenderer = (props: { key: string; index: number; style: React.CSSProperties }) => {\n            const item = this.props.items[props.index]\n            return (\n                <div style={props.style} key={props.key}>\n                    <MenuItem\n                        {...item as any}\n                        key={props.key}\n                        filterText={this.props.filterText}\n                        isSelected={props.index === this.props.selectedIndex}\n                        onClick={() => this.props.onSelect(props.index)}\n                    />\n                </div>\n            )\n        }\n\n        const footerClassName = \"footer \" + (this.props.isLoading ? \"loading\" : \"loaded\")\n\n        const height =\n            Math.min(this.props.items.length, this.props.maxItemsToShow) * this.props.rowHeight\n\n        return (\n            <div className=\"menu-background enable-mouse\" onClick={this.handleHide}>\n                <MenuStyleWrapper\n                    className=\"menu\"\n                    innerRef={elem => {\n                        this._popupBody = elem\n                    }}\n                >\n                    <TextInputView onChange={evt => this._onChange(evt)} />\n                    <div className=\"items\">\n                        <div>\n                            <AutoSizer disableHeight={true}>\n                                {({ width }) => (\n                                    <List\n                                        scrollToIndex={this.props.selectedIndex}\n                                        width={width}\n                                        height={height}\n                                        rowCount={this.props.items.length}\n                                        rowHeight={this.props.rowHeight}\n                                        rowRenderer={rowRenderer}\n                                    />\n                                )}\n                            </AutoSizer>\n                        </div>\n                    </div>\n                    <div className={footerClassName}>\n                        <div className=\"loading-spinner\">\n                            <Icon\n                                name=\"circle-o-notch\"\n                                className=\" fa-spin\"\n                                size={IconSize.Large}\n                            />\n                        </div>\n                    </div>\n                </MenuStyleWrapper>\n            </div>\n        )\n    }\n\n    private _onChange(evt: React.FormEvent<HTMLInputElement>) {\n        const target: any = evt.target\n        this.props.onChangeFilterText(target.value)\n    }\n\n    /**\n     * Hide the popup if a click event was registered outside of it\n     */\n    private handleHide = (event: any) => {\n        const node = ReactDOM.findDOMNode(this._popupBody)\n        if (!node.contains(event.target as Node)) {\n            this.props.onHide()\n        }\n    }\n}\n\nconst EmptyArray: any[] = []\nconst noop = () => {} // tslint:disable-line\nconst NullProps: any = {\n    visible: false,\n    selectedIndex: 0,\n    filterText: \"\",\n    items: EmptyArray,\n    onSelect: noop,\n    isLoading: true,\n    rowHeight: 0,\n    maxItemsToShow: 0,\n}\n\nconst mapStateToProps = (\n    state: State.IMenus<Oni.Menu.MenuOption, IMenuOptionWithHighlights>,\n): any => {\n    if (!state.menu) {\n        return NullProps\n    } else {\n        const popupMenu = state.menu\n        return {\n            visible: true,\n            selectedIndex: popupMenu.selectedIndex,\n            filterText: popupMenu.filter,\n            items: popupMenu.filteredOptions,\n            onSelect: popupMenu.onSelectItem,\n            isLoading: popupMenu.isLoading,\n            rowHeight: state.configuration.rowHeight,\n            maxItemsToShow: state.configuration.maxItemsToShow,\n        }\n    }\n}\n\nconst mapDispatchToProps = {\n    onChangeFilterText: ActionCreators.filterMenu,\n    onHide: ActionCreators.hidePopupMenu,\n}\n\nexport const ConnectedMenu: any = connect(mapStateToProps, mapDispatchToProps)(MenuView)\n\nexport const MenuContainer = () => {\n    return (\n        <Provider store={menuStore}>\n            <ConnectedMenu />\n        </Provider>\n    )\n}\n\nexport interface IMenuItemProps {\n    icon?: string | JSX.Element\n    isSelected: boolean\n    filterText: string\n    label: string\n    labelHighlights: number[]\n    detail: string\n    detailHighlights: number[]\n    pinned: boolean\n    additionalComponent?: JSX.Element\n    onClick: () => void\n    height: number\n}\n\nexport interface IMenuItemWrapperProps {\n    isSelected: boolean\n    borderSize?: string\n}\n\nconst MenuItemWrapper = withProps<IMenuItemWrapperProps>(styled.div)`\n    position: absolute;\n    top: 4px;\n    left: 0px;\n    right: 4px;\n    bottom: 4px;\n\n    border-left: ${getSelectedBorder};\n\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n\n    user-select: none;\n    -webkit-user-drag:none;\n    cursor: pointer;\n    font-size: 1em;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n`\n\nexport class MenuItem extends React.PureComponent<IMenuItemProps, {}> {\n    public render(): JSX.Element {\n        const className = \"item\" + (this.props.isSelected ? \" selected\" : \"\")\n\n        return (\n            <MenuItemWrapper\n                borderSize=\"4px\"\n                isSelected={this.props.isSelected}\n                className={className}\n                onClick={() => this.props.onClick()}\n                style={{ height: this.props.height + \"px\" }}\n            >\n                {this.getIcon()}\n                <HighlightTextByIndex\n                    className=\"label\"\n                    text={this.props.label}\n                    highlightIndices={this.props.labelHighlights}\n                    highlightComponent={LabelHighlight}\n                />\n                <HighlightTextByIndex\n                    className=\"detail\"\n                    text={this.props.detail}\n                    highlightIndices={this.props.detailHighlights}\n                    highlightComponent={DetailHighlight}\n                />\n                {this.props.additionalComponent}\n                {renderPinnedIcon({ pinned: this.props.pinned })}\n            </MenuItemWrapper>\n        )\n    }\n\n    private getIcon() {\n        if (!this.props.icon) {\n            return <Icon name={\"default\"} />\n        }\n        if (typeof this.props.icon === \"string\") {\n            return <Icon name={this.props.icon} />\n        }\n        return this.props.icon\n    }\n}\n\nconst LabelHighlight = styled.span`\n    font-weight: bold;\n    color: ${props => props.theme[\"highlight.mode.normal.background\"]};\n`\n\nconst DetailHighlight = styled.span`\n    font-weight: bold;\n    color: #757575;\n`\n"
  },
  {
    "path": "browser/src/Services/Menu/MenuReducer.ts",
    "content": "/**\n * MenuReducer.ts\n *\n * Implements state-change logic for the menu\n */\n\nimport { filter } from \"./Filter/FuseFilter\"\nimport * as Actions from \"./MenuActions\"\nimport * as State from \"./MenuState\"\n\nexport function createReducer<T, FilteredT extends T>() {\n    const reducer = (\n        s: State.IMenus<T, FilteredT>,\n        a: Actions.MenuAction,\n    ): State.IMenus<T, FilteredT> => {\n        return {\n            ...s,\n            configuration: configurationReducer(s.configuration, a),\n            menu: popupMenuReducer(s.menu, a),\n        }\n    }\n\n    const configurationReducer = (\n        s: State.IMenuConfigurationSettings = State.DefaultMenuConfigurationSettings,\n        a: Actions.MenuAction,\n    ) => {\n        switch (a.type) {\n            case \"SET_MENU_CONFIGURATION\":\n                return {\n                    ...s,\n                    rowHeight: a.payload.rowHeight,\n                    maxItemsToShow: a.payload.maxItemsToShow,\n                }\n            default:\n                return s\n        }\n    }\n\n    function popupMenuReducer(\n        s: State.IMenu<T, FilteredT> | null,\n        a: any,\n    ): State.IMenu<T, FilteredT> {\n        // TODO: sync max display items (10) with value in Menu.render() (Menu.tsx)\n        const size = s && s.filteredOptions ? s.filteredOptions.length : 0\n\n        switch (a.type) {\n            case \"SHOW_MENU\": {\n                const options3 = a.payload.items || []\n                const filterText = a.payload.filter || \"\"\n                const filterFunc =\n                    a.payload.options && a.payload.options.filterFunction\n                        ? a.payload.options.filterFunction\n                        : filter\n                const filteredOptions3 = filterFunc(options3, filterText)\n                return {\n                    ...a.payload.options,\n                    id: a.payload.id,\n                    filter: filterText,\n                    filterFunction: filterFunc,\n                    filteredOptions: filteredOptions3,\n                    options: options3,\n                    selectedIndex: 0,\n                    isLoading: false,\n                }\n            }\n            case \"SET_MENU_ITEMS\": {\n                if (!s || s.id !== a.payload.id) {\n                    return s\n                }\n\n                const filterFunc = s.filterFunction\n                const filteredOptions = filterFunc(a.payload.items, s.filter)\n\n                return {\n                    ...s,\n                    options: a.payload.items,\n                    filteredOptions,\n                }\n            }\n            case \"SET_MENU_LOADING\":\n                if (!s || s.id !== a.payload.id) {\n                    return s\n                }\n\n                return {\n                    ...s,\n                    isLoading: a.payload.isLoading,\n                }\n            case \"HIDE_MENU\":\n                return null\n            case \"NEXT_MENU\":\n                return {\n                    ...s,\n                    selectedIndex: (s.selectedIndex + 1) % size,\n                }\n            case \"PREVIOUS_MENU\":\n                return {\n                    ...s,\n                    selectedIndex: s.selectedIndex > 0 ? s.selectedIndex - 1 : size - 1,\n                }\n            case \"FILTER_MENU\": {\n                if (!s) {\n                    return s\n                }\n\n                // Note that for language server completions, the `filterFunc` is a no-op - the\n                // items are filtered elsewhere (but this FILTER_MENU action is still dispatched).\n                const filterFunc = s.filterFunction\n                const filteredOptionsSorted = filterFunc(s.options, a.payload.filter)\n\n                return {\n                    ...s,\n                    filter: a.payload.filter,\n                    filteredOptions: filteredOptionsSorted,\n                    selectedIndex: 0,\n                }\n            }\n            default:\n                return s\n        }\n    }\n\n    return reducer\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/MenuState.ts",
    "content": "/**\n * MenuState.ts\n *\n * Definition of State for Menu functionality\n */\n\nexport interface IMenus<T, FilteredT> {\n    // TOOD: In the future, could handle multiple menus here...\n    menu: IMenu<T, FilteredT>\n    configuration: IMenuConfigurationSettings\n}\n\nexport interface IMenuConfigurationSettings {\n    rowHeight: number\n    maxItemsToShow: number\n}\n\nexport const DefaultMenuConfigurationSettings: IMenuConfigurationSettings = {\n    rowHeight: 40,\n    maxItemsToShow: 6,\n}\n\nexport interface IMenu<T, FilteredT> {\n    id: string\n    filter: string\n    filteredOptions: FilteredT[]\n    options: T[]\n    selectedIndex: number\n    isLoading: boolean\n\n    backgroundColor: string\n    foregroundColor: string\n    borderColor: string\n    highlightColor: string\n\n    filterFunction: (items: T[], searchString: string) => FilteredT[]\n\n    onFilterTextChanged: (newText: string) => void\n    onSelectedItemChanged: (newItem: FilteredT) => void\n    onSelectItem: (idx: number) => void\n    onHide: () => void\n}\n\nexport function createDefaultState<T, FilteredT>(): IMenus<T, FilteredT> {\n    return {\n        menu: null,\n        configuration: {\n            rowHeight: 20,\n            maxItemsToShow: 10,\n        },\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/PinnedIconView.tsx",
    "content": "/**\n * PinnedIconView.tsx\n *\n * Shows the pinned icon for recently navigated items in quick open\n */\n\nimport * as React from \"react\"\n\nimport { Visible } from \"./../../UI/components/Visible\"\nimport { Icon } from \"./../../UI/Icon\"\n\nexport const render = (props: { pinned: boolean }) => {\n    return (\n        <Visible visible={props.pinned}>\n            <Icon name=\"clock-o\" />\n        </Visible>\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Menu/index.ts",
    "content": "export * from \"./Menu\"\nexport * from \"./MenuComponent\"\nexport * from \"./Filter\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { OverlayManager } from \"./../Overlay\"\nimport { MenuManager } from \"./Menu\"\n\nlet _menuManager: MenuManager\n\nexport const activate = (configuration: Configuration, overlayManager: OverlayManager) => {\n    _menuManager = new MenuManager(configuration, overlayManager)\n}\n\nexport const getInstance = (): MenuManager => {\n    return _menuManager\n}\n"
  },
  {
    "path": "browser/src/Services/Metadata.ts",
    "content": "/**\n * Metadata.ts\n *\n * Provides information about Oni's pkg\n */\n\nimport { readFile } from \"fs-extra\"\nimport * as Log from \"oni-core-logging\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nexport interface IMetadata {\n    name: string\n    version: string\n}\n\nexport const getMetadata = async (): Promise<IMetadata> => {\n    const packageMetadata = path.join(__dirname, \"package.json\")\n    try {\n        const data = await readFile(packageMetadata, \"utf8\")\n        const pkg = JSON.parse(data)\n        const metadata = { name: pkg.name, version: pkg.version }\n        return metadata\n    } catch (e) {\n        Log.warn(`Oni Error: failed to fetch Oni package metadata because ${e.message}`)\n        return { name: null, version: null }\n    }\n}\n\nexport const showAboutMessage = async () => {\n    const metadata = await getMetadata()\n\n    const infoLines = [\n        `${metadata.name} version ${metadata.version}`,\n        \"https://www.onivim.io\",\n        \"\",\n        \"Copyright 2018 Bryan Phelps\",\n        \"MIT License\",\n    ]\n\n    alert(infoLines.join(os.EOL))\n}\n"
  },
  {
    "path": "browser/src/Services/MultiProcess.ts",
    "content": "/**\n * MultiProcess.ts\n *\n * Utilities for managing interop between multiple open instances of ONI\n */\n\nimport { ipcRenderer } from \"electron\"\nimport { WindowManager } from \"./WindowManager\"\n\nexport class MultiProcess {\n    public focusPreviousInstance(): void {\n        ipcRenderer.send(\"focus-previous-instance\")\n    }\n\n    public focusNextInstance(): void {\n        ipcRenderer.send(\"focus-next-instance\")\n    }\n\n    public moveToNextOniInstance(direction: string): void {\n        ipcRenderer.send(\"move-to-next-oni-instance\", direction)\n    }\n\n    public openNewWindow(): void {\n        ipcRenderer.send(\"open-oni-window\")\n    }\n}\n\nexport const activate = (windowManager: WindowManager): void => {\n    // Wire up accepting unhandled moves to swap to the next\n    // available Oni instance.\n    windowManager.onUnhandledMove.subscribe((direction: string) => {\n        multiProcess.moveToNextOniInstance(direction)\n    })\n}\n\nexport const multiProcess = new MultiProcess()\n"
  },
  {
    "path": "browser/src/Services/Notifications/Notification.ts",
    "content": "/**\n * Notification.ts\n *\n * API interface for notification UX\n */\n\nimport { Store } from \"redux\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { INotificationButton, INotificationsState, NotificationLevel } from \"./NotificationStore\"\n\nexport class Notification {\n    private _title: string = \"\"\n    private _detail: string = \"\"\n    private _buttons: INotificationButton[]\n    private _expirationTime: number\n    private _level: NotificationLevel = \"info\"\n\n    private _onClickEvent = new Event<void>()\n    private _onCloseEvent = new Event<void>()\n\n    public get onClick(): IEvent<void> {\n        return this._onClickEvent\n    }\n\n    public get onClose(): IEvent<void> {\n        return this._onCloseEvent\n    }\n\n    constructor(private _id: string, private _store: Store<INotificationsState>) {}\n\n    public setContents(title: string, detail: string): void {\n        this._title = title\n        this._detail = detail\n    }\n\n    public setButtons(buttons: INotificationButton[]) {\n        // only set valid values\n        if (buttons && buttons.every(b => !!(b.title && b.callback))) {\n            this._buttons = buttons\n        }\n    }\n\n    public setLevel(level: NotificationLevel): void {\n        this._level = level\n    }\n\n    public setExpiration(expiration: number = 20000) {\n        if (this._level !== \"error\") {\n            this._expirationTime = expiration\n        }\n    }\n\n    public show(): void {\n        this._store.dispatch({\n            type: \"SHOW_NOTIFICATION\",\n            id: this._id,\n            title: this._title,\n            detail: this._detail,\n            buttons: this._buttons,\n            level: this._level,\n            expirationTime: this._expirationTime,\n            onClick: () => {\n                this._onClickEvent.dispatch()\n                this.hide()\n            },\n            onClose: () => {\n                this._onCloseEvent.dispatch()\n                this.hide()\n            },\n        })\n    }\n\n    public hide(): void {\n        this._store.dispatch({\n            type: \"HIDE_NOTIFICATION\",\n            id: this._id,\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Notifications/NotificationStore.ts",
    "content": "/**\n * NotificationStore.ts\n *\n * State management for Notifications\n */\n\nimport { Reducer, Store } from \"redux\"\nimport { combineEpics, createEpicMiddleware, Epic } from \"redux-observable\"\nimport { Observable } from \"rxjs\"\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nexport type NotificationLevel = \"info\" | \"warn\" | \"error\" | \"success\"\n\nexport interface INotificationButton {\n    title: string\n    callback: (args?: any) => void\n}\n\nexport interface IdToNotification {\n    [key: string]: INotification\n}\n\nexport interface INotificationsState {\n    notifications: IdToNotification\n}\n\nexport const DefaultNotificationState: INotificationsState = {\n    notifications: {},\n}\n\nexport interface INotification {\n    id: string\n    level: NotificationLevel\n    title: string\n    detail: string\n    expirationTime: number\n    buttons?: INotificationButton[]\n    onClick: () => void\n    onClose: () => void\n}\n\ninterface IShowNotification {\n    type: \"SHOW_NOTIFICATION\"\n    id: string\n    level: NotificationLevel\n    buttons: INotificationButton[]\n    title: string\n    detail: string\n    expirationTime: number\n    onClick: () => void\n    onClose: () => void\n}\n\ninterface IHideNotification {\n    type: \"HIDE_NOTIFICATION\"\n    id: string\n}\n\nexport type NotificationAction = IShowNotification | IHideNotification\n\nexport const notificationsReducer: Reducer<IdToNotification> = (\n    state: IdToNotification = {},\n    action: NotificationAction,\n) => {\n    switch (action.type) {\n        case \"SHOW_NOTIFICATION\":\n            return {\n                ...state,\n                [action.id]: {\n                    id: action.id,\n                    level: action.level,\n                    title: action.title,\n                    detail: action.detail,\n                    buttons: action.buttons,\n                    onClick: action.onClick,\n                    onClose: action.onClose,\n                    expirationTime: action.expirationTime,\n                },\n            }\n        case \"HIDE_NOTIFICATION\":\n            return {\n                ...state,\n                [action.id]: null,\n            }\n        default:\n            return state\n    }\n}\n\nconst hideNotificationAfterExpirationEpic: Epic<NotificationAction, INotificationsState> = (\n    action$,\n    store,\n) => {\n    return action$\n        .ofType(\"SHOW_NOTIFICATION\")\n        .filter((action: IShowNotification) => !!action.expirationTime)\n        .mergeMap(({ expirationTime, id }: IShowNotification) => {\n            return Observable.timer(expirationTime).mapTo({\n                type: \"HIDE_NOTIFICATION\",\n                id,\n            } as IHideNotification)\n        })\n}\nexport const stateReducer: Reducer<INotificationsState> = (\n    state: INotificationsState = DefaultNotificationState,\n    action: NotificationAction,\n) => {\n    return {\n        notifications: notificationsReducer(state.notifications, action),\n    }\n}\n\nexport const createStore = (): Store<INotificationsState> => {\n    return createReduxStore(\"Notifications\", stateReducer, DefaultNotificationState, [\n        createEpicMiddleware(combineEpics(hideNotificationAfterExpirationEpic)),\n    ])\n}\n"
  },
  {
    "path": "browser/src/Services/Notifications/Notifications.ts",
    "content": "/**\n * Notifications.ts\n *\n * API interface and lifecycle manager for notifications UX\n */\n\nimport { Store } from \"redux\"\n\nimport { Overlay, OverlayManager } from \"./../Overlay\"\n\nimport { Notification } from \"./Notification\"\nimport { createStore, INotificationsState } from \"./NotificationStore\"\n\nimport { getView } from \"./NotificationsView\"\n\nexport class Notifications {\n    private _id: number = 0\n    private _overlay: Overlay\n    private _store: Store<INotificationsState>\n\n    constructor(private _overlayManager: OverlayManager) {\n        this._store = createStore()\n\n        this._overlay = this._overlayManager.createItem()\n        this._overlay.setContents(getView(this._store))\n    }\n\n    public enable(): void {\n        this._overlay.show()\n    }\n\n    public disable(): void {\n        this._overlay.hide()\n    }\n\n    public createItem(): Notification {\n        this._id++\n\n        return new Notification(\"notification\" + this._id.toString(), this._store)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Notifications/NotificationsView.tsx",
    "content": "/**\n * NotificationsView.tsx\n *\n * View / React layer for Notifications\n */\n\nimport * as React from \"react\"\n\nimport { connect, Provider } from \"react-redux\"\n\nimport { CSSTransition, TransitionGroup } from \"react-transition-group\"\n\nimport {\n    INotification,\n    INotificationButton,\n    INotificationsState,\n    NotificationLevel,\n} from \"./NotificationStore\"\n\nimport { boxShadow, keyframes, lighten, styled, withProps } from \"./../../UI/components/common\"\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\nimport { Icon, IconSize } from \"./../../UI/Icon\"\n\nexport interface NotificationsViewProps {\n    notifications: INotification[]\n}\n\nconst Transition = (props: { children: React.ReactNode }) => {\n    return (\n        <CSSTransition {...props} timeout={1000} classNames=\"notification\">\n            {props.children}\n        </CSSTransition>\n    )\n}\n\nconst NotificationsWrapper = styled.div`\n    position: absolute;\n    top: 1em;\n    right: 1em;\n    max-height: 90%;\n    max-width: 33vw;\n    pointer-events: all;\n    overflow: auto;\n\n    .notification:first-child {\n        margin-top: 0;\n    }\n`\n\nexport class NotificationsView extends React.PureComponent<NotificationsViewProps, {}> {\n    public render(): JSX.Element {\n        return (\n            <NotificationsWrapper>\n                <TransitionGroup>\n                    {this.props.notifications.map(notification => {\n                        return (\n                            <Transition>\n                                <NotificationView {...notification} key={notification.id} />\n                            </Transition>\n                        )\n                    })}\n                </TransitionGroup>\n            </NotificationsWrapper>\n        )\n    }\n}\n\nconst frames = keyframes`\n    0% { opacity: 0; transform: translateY(4px); }\n    100% { opacity: 1; transform: translateY(0px); }\n`\n\ninterface IErrorStyles {\n    level?: NotificationLevel\n}\n\nconst getColorForErrorLevel = (level: NotificationLevel) => {\n    const colorToLevel = {\n        warn: \"yellow\",\n        error: \"red\",\n        info: \"#1D7CF2\", // blue\n        success: \"#5AB379\", // green\n    }\n\n    return colorToLevel[level]\n}\n\nconst NotificationWrapper = withProps<IErrorStyles>(styled.div)`\n    background-color: ${p => p.theme[\"toolTip.background\"]};\n    border-radius: 4px;\n    border-left: solid 4px ${p => getColorForErrorLevel(p.level)};\n    padding: 0 1rem 1rem;\n    color: white;\n    margin: 1rem 0 1rem 1rem;\n    ${boxShadow};\n\n    max-height: 50%;\n\n    display: flex;\n    flex: auto;\n    flex-direction: column;\n\n    justify-content: center;\n    align-items: center;\n\n    pointer-events: auto;\n    cursor: pointer;\n\n    overflow: hidden;\n    transition: all 0.1s ease-in;\n\n    &.notification-enter {\n        animation: ${frames} 0.25s ease-in;\n    }\n\n    &.notification-exit {\n        animation: ${frames} 0.25s ease-in both reverse;\n    }\n\n    &:hover {\n        transform: translateY(-1px);\n    }\n`\n\nconst IconContainer = styled.div`\n    display: flex;\n    width: 100%;\n    flex-direction: row;\n    align-items: center;\n    justify-content: space-between;\n`\n\nconst NotificationIconWrapper = withProps<IErrorStyles>(styled.div)`\n    ${({ level }) => level && `color: ${getColorForErrorLevel(level)};`};\n    flex: 0 0 auto;\n    align-self: flex-start;\n\n    padding: 8px;\n\n    &:hover {\n        ${boxShadow};\n        transform: translateY(-1px);\n    }\n`\n\nexport const NotificationContents = styled.div`\n    flex: 1 1 auto;\n    width: 100%;\n\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n\n    padding: 8px;\n\n    overflow-y: auto;\n    overflow-x: hidden;\n`\n\nexport const NotificationTitle = withProps<IErrorStyles>(styled.div)`\n    ${({ level }) => level && `color: ${getColorForErrorLevel(level)};`};\n    flex: 0 0 auto;\n    width: 100%;\n    word-break: break-word;\n    font-weight: bold;\n    font-size: 1.1em;\n`\n\nexport const NotificationDescription = styled.div`\n    flex: 1 1 auto;\n    overflow-y: auto;\n    overflow-x: hidden;\n    margin: 1em 0em;\n\n    font-size: 0.9em;\n`\n\nconst NotificationHeader = styled.header`\n    width: 100%;\n    display: flex;\n    flex-wrap: wrap;\n    flex-direction: row;\n    justify-content: space-between;\n    align-items: center;\n    border-bottom: 1px solid ${p => p.theme[\"toolTip.border\"]};\n    padding: 0.5rem;\n`\n\nconst ButtonRow = styled.div`\n    width: 100%;\n    height: 10%;\n    display: flex;\n    justify-content: flex-end;\n`\n\nexport const Button = styled.button`\n    border: none;\n    cursor: pointer;\n    text-align: center;\n    overflow: hidden;\n    min-width: 5em;\n    min-height: 2em;\n    border-radius: 4px;\n    font-size: 0.9em;\n    font-family: inherit;\n    display: inline-block;\n    margin: 0 0.5em;\n    ${boxShadow};\n    ${({ theme }) => `\n        background-color: ${lighten(theme[\"editor.background\"], 0.25)};\n        color: ${theme[\"editor.foreground\"]};\n    `};\n`\n\ninterface IButtonProps {\n    buttons: INotificationButton[]\n    onClose: () => void\n}\n\nconst Buttons = ({ buttons, onClose }: IButtonProps) => {\n    const executeThenClose = (callback: (args?: any) => void) => () => {\n        callback()\n        onClose()\n    }\n    return (\n        <ButtonRow data-test=\"notification-buttons\">\n            {buttons.map(({ callback, title }, index) => (\n                <Sneakable key={`${title}-${index}`} callback={executeThenClose(callback)}>\n                    <Button data-test={`notification-${title.toLowerCase()}`} onClick={callback}>\n                        {title}\n                    </Button>\n                </Sneakable>\n            ))}\n        </ButtonRow>\n    )\n}\n\nexport class NotificationView extends React.PureComponent<INotification, {}> {\n    private iconDictionary = {\n        error: \"times-circle\",\n        warn: \"exclamation-triangle\",\n        info: \"info-circle\",\n        success: \"check-circle\",\n    }\n\n    public render(): JSX.Element {\n        const { level, buttons } = this.props\n        return (\n            <NotificationWrapper\n                data-test=\"notification\"\n                key={this.props.id}\n                onClick={this.props.onClick}\n                className=\"notification\"\n                level={level}\n            >\n                <NotificationHeader>\n                    <IconContainer>\n                        <NotificationIconWrapper level={level}>\n                            <Sneakable callback={this.props.onClick}>\n                                <Icon size={IconSize.Large} name={this.iconDictionary[level]} />\n                            </Sneakable>\n                        </NotificationIconWrapper>\n                        <NotificationIconWrapper onClick={evt => this._onClickClose(evt)}>\n                            <Sneakable callback={this.props.onClose}>\n                                <Icon size={IconSize.Large} name=\"times\" />\n                            </Sneakable>\n                        </NotificationIconWrapper>\n                    </IconContainer>\n                    <NotificationTitle data-test=\"notification-title\" level={level}>\n                        {this.props.title}\n                    </NotificationTitle>\n                </NotificationHeader>\n                <NotificationContents>\n                    <NotificationDescription className=\"notification-description\">\n                        {this.props.detail}\n                    </NotificationDescription>\n                </NotificationContents>\n                {buttons && <Buttons onClose={this.props.onClose} buttons={buttons} />}\n            </NotificationWrapper>\n        )\n    }\n\n    private _onClickClose = (evt: React.MouseEvent<HTMLElement>): void => {\n        this.props.onClose()\n        evt.stopPropagation()\n        evt.preventDefault()\n    }\n}\n\nexport const mapStateToProps = (state: INotificationsState): NotificationsViewProps => {\n    const objs = Object.keys(state.notifications).map(key => state.notifications[key])\n\n    const activeNotifications = objs.filter(o => o !== null)\n\n    return {\n        notifications: activeNotifications,\n    }\n}\n\nconst NotificationsContainer = connect(mapStateToProps)(NotificationsView)\n\nexport const getView = (store: any) => (\n    <Provider store={store}>\n        <NotificationsContainer />\n    </Provider>\n)\n"
  },
  {
    "path": "browser/src/Services/Notifications/index.ts",
    "content": "/**\n * index.ts\n */\n\nimport * as Log from \"oni-core-logging\"\n\nimport { OverlayManager } from \"./../Overlay\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { Notifications } from \"./Notifications\"\n\nexport * from \"./Notifications\"\n\nlet _notifications: Notifications = null\n\nexport const activate = (configuration: Configuration, overlayManager: OverlayManager): void => {\n    _notifications = new Notifications(overlayManager)\n\n    const updateFromConfiguration = () => {\n        const areNotificationsEnabled = configuration.getValue(\"notifications.enabled\")\n        Log.info(\"[Notifications] Setting enabled: \" + areNotificationsEnabled)\n        areNotificationsEnabled ? _notifications.enable() : _notifications.disable()\n    }\n\n    configuration.onConfigurationChanged.subscribe(val => {\n        if (typeof val[\"notifications.enabled\"] === \"boolean\") {\n            updateFromConfiguration()\n        }\n    })\n\n    updateFromConfiguration()\n}\n\nexport const getInstance = (): Notifications => {\n    return _notifications\n}\n"
  },
  {
    "path": "browser/src/Services/Overlay.ts",
    "content": "/**\n * Overlay.ts\n *\n * API adapter for the Overlay store actions\n */\n\nimport * as Shell from \"./../UI/Shell\"\n\nexport class Overlay {\n    private _contents: JSX.Element\n    private _visible: boolean = false\n\n    constructor(private _id: string) {}\n\n    public show(): void {\n        this._visible = true\n        Shell.Actions.showOverlay(this._id, this._contents)\n    }\n\n    public hide(): void {\n        this._visible = false\n        Shell.Actions.hideOverlay(this._id)\n    }\n\n    public setContents(element: any): void {\n        this._contents = element\n\n        if (this._visible) {\n            Shell.Actions.showOverlay(this._id, this._contents)\n        }\n    }\n}\n\nexport class OverlayManager {\n    private _id: number = 0\n\n    public createItem(): Overlay {\n        this._id++\n\n        return new Overlay(\"overlay\" + this._id.toString())\n    }\n}\n\nlet _overlays: OverlayManager = null\nexport const activate = (): void => {\n    _overlays = new OverlayManager()\n}\n\nexport const getInstance = (): OverlayManager => {\n    return _overlays\n}\n"
  },
  {
    "path": "browser/src/Services/Particles/ParticleSystem.tsx",
    "content": "/**\n * ParticleSystem.tsx\n *\n * Lightweight, canvas-based particle system\n *\n * TODO:\n *  - Move this to a plugin, and access via the `getPlugin` API\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nimport { Overlay, OverlayManager } from \"./../Overlay\"\n\nexport interface Vector {\n    x: number\n    y: number\n}\n\nexport interface ParticleSystemDefinition {\n    // StartSize: number\n    // EndSize: number\n\n    Position: Vector\n    Velocity: Vector\n    PositionVariance: Vector\n    VelocityVariance: Vector\n    Color: string\n\n    StartOpacity: number\n    EndOpacity: number\n\n    Gravity: Vector\n\n    Time: number\n}\n\nconst ZeroVector = { x: 0, y: 0 }\n\nexport const DefaultParticleSystemDefinition: Partial<ParticleSystemDefinition> = {\n    Color: \"white\",\n    StartOpacity: 1,\n    EndOpacity: 0,\n    Gravity: { x: 0, y: 500 },\n    Time: 1,\n    Position: ZeroVector,\n    Velocity: ZeroVector,\n    PositionVariance: ZeroVector,\n    VelocityVariance: ZeroVector,\n}\n\nexport interface Particle {\n    position: Vector\n    opacity: number\n    color: string\n\n    velocity: Vector\n    opacityVelocity: number\n    gravity: Vector\n\n    remainingTime: number\n}\n\nconst StyledCanvas = styled.canvas`\n    width: 100%;\n    height: 100%;\n`\n\n/**\n * Lightweight canvas-based particle system renderer\n */\nexport class ParticleSystem {\n    private _activeParticles: Particle[] = []\n    private _activeOverlay: Overlay\n    private _activeCanvas: HTMLCanvasElement\n\n    private _lastTime: number\n    private _enabled: boolean = false\n\n    constructor(private _overlayManager: OverlayManager) {}\n\n    public get enabled(): boolean {\n        return this._enabled\n    }\n    public set enabled(val: boolean) {\n        this._enabled = val\n    }\n\n    public createParticles(count: number, particleSystem: Partial<ParticleSystemDefinition>): void {\n        const newParticles: Particle[] = []\n\n        const system = {\n            ...DefaultParticleSystemDefinition,\n            ...particleSystem,\n        }\n\n        for (let i = 0; i < count; i++) {\n            newParticles.push({\n                position: {\n                    x: system.Position.x + (Math.random() - 0.5) * system.PositionVariance.x,\n                    y: system.Position.y + (Math.random() - 0.5) * system.PositionVariance.y,\n                },\n                color: system.Color,\n                opacity: system.StartOpacity,\n                velocity: {\n                    x: system.Velocity.x + (Math.random() - 0.5) * system.VelocityVariance.x,\n                    y: system.Velocity.y + (Math.random() - 0.5) * system.VelocityVariance.y,\n                },\n                gravity: system.Gravity,\n                opacityVelocity: (system.EndOpacity - system.StartOpacity) / system.Time,\n                remainingTime: system.Time,\n            })\n        }\n\n        this._activeParticles = [...this._activeParticles, ...newParticles]\n\n        if (!this._activeOverlay) {\n            this._activeOverlay = this._overlayManager.createItem()\n        }\n\n        this._activeOverlay.show()\n        this._activeOverlay.setContents(\n            <StyledCanvas className=\"particles\" innerRef={elem => (this._activeCanvas = elem)} />,\n        )\n\n        this._start()\n    }\n\n    private _start(): void {\n        this._lastTime = new Date().getTime()\n        window.requestAnimationFrame(() => {\n            this._update()\n        })\n    }\n\n    private _update(): void {\n        const currentTime = new Date().getTime()\n        const deltaTime = (currentTime - this._lastTime) / 1000\n        this._lastTime = currentTime\n\n        const updatedParticles = this._activeParticles.map(p => {\n            return {\n                ...p,\n                position: {\n                    x: p.position.x + p.velocity.x * deltaTime,\n                    y: p.position.y + p.velocity.y * deltaTime,\n                },\n                velocity: {\n                    x: p.velocity.x + p.gravity.x * deltaTime,\n                    y: p.velocity.y + p.gravity.y * deltaTime,\n                },\n                opacity: p.opacity + p.opacityVelocity * deltaTime,\n                remainingTime: p.remainingTime - deltaTime,\n            }\n        })\n\n        const filteredParticles = updatedParticles.filter(p => p.remainingTime >= 0)\n\n        this._activeParticles = filteredParticles\n\n        this._draw()\n\n        if (this._activeParticles.length > 0) {\n            window.requestAnimationFrame(() => this._update())\n        } else {\n            if (this._activeOverlay) {\n                this._activeOverlay.hide()\n            }\n        }\n    }\n\n    private _draw(): void {\n        if (!this._activeCanvas) {\n            return\n        }\n\n        const context = this._activeCanvas.getContext(\"2d\", { alpha: true })\n        const width = (this._activeCanvas.width = this._activeCanvas.offsetWidth)\n        const height = (this._activeCanvas.height = this._activeCanvas.offsetHeight)\n        context.clearRect(0, 0, width, height)\n\n        this._activeParticles.forEach(p => {\n            context.fillStyle = p.color\n            context.globalAlpha = p.opacity\n            context.fillRect(p.position.x, p.position.y, 2, 2)\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Particles/index.tsx",
    "content": "/**\n * index.tsx\n *\n * Entry point for particle system\n */\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { OverlayManager } from \"./../Overlay\"\n\nimport { ParticleSystem } from \"./ParticleSystem\"\n\nexport * from \"./ParticleSystem\"\n\nlet _engine: ParticleSystem = null\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n    overlay: OverlayManager,\n) => {\n    _engine = new ParticleSystem(overlay)\n\n    if (configuration.getValue(\"experimental.particles.enabled\")) {\n        _engine.enabled = true\n\n        commandManager.registerCommand({\n            command: \"debug.particles.test\",\n            name: null,\n            detail: null,\n            execute: () => {\n                _engine.createParticles(25, {\n                    Position: { x: 600, y: 500 },\n                    PositionVariance: { x: 10, y: 10 },\n                    Velocity: { x: 0, y: -350 },\n                    VelocityVariance: { x: 200, y: 50 },\n                    Color: \"white\",\n                    StartOpacity: 1,\n                    EndOpacity: 0,\n                    Time: 1,\n                })\n            },\n        })\n    }\n}\n\nexport const getInstance = (): ParticleSystem => {\n    return _engine\n}\n"
  },
  {
    "path": "browser/src/Services/Preview/PreviewBufferLayer.tsx",
    "content": "/**\n * PreviewBufferLayer.tsx\n *\n * Buffer layer for showing preview\n */\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\n\nimport styled from \"styled-components\"\n\nimport { withProps } from \"./../../UI/components/common\"\n\nimport { EditorManager } from \"./../EditorManager\"\nimport { IPreviewer, Preview } from \"./index\"\n\nconst PreviewWrapper = withProps<{}>(styled.div)`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n    background-color: ${p => p.theme[\"editor.background\"]};\n    color: ${p => p.theme[\"editor.foreground\"]};\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nexport class PreviewBufferLayer implements Oni.BufferLayer {\n    constructor(private _editorManager: EditorManager, private _preview: Preview) {}\n\n    public get id(): string {\n        return \"oni.layer.preview\"\n    }\n\n    public render(): JSX.Element {\n        return <PreviewView editorManager={this._editorManager} previewManager={this._preview} />\n    }\n}\n\nexport interface IPreviewViewProps {\n    editorManager: EditorManager\n    previewManager: Preview\n}\n\nexport interface IPreviewViewState {\n    filePath: string\n    language: string\n\n    previewer: IPreviewer\n}\n\nexport class PreviewView extends React.PureComponent<IPreviewViewProps, IPreviewViewState> {\n    // private _filePath = \"E:/oni/lib_test/browser/src/UI/components/Arrow\"\n\n    constructor(props: any) {\n        super(props)\n        this.state = {\n            previewer: null,\n            filePath: null,\n            language: null,\n        }\n    }\n\n    public componentDidMount(): void {\n        const currentBuffer = this.props.editorManager.activeEditor.activeBuffer\n\n        if (currentBuffer) {\n            const currentPreviewer = this.props.previewManager.getPreviewer(currentBuffer.language)\n            this.setState({\n                previewer: currentPreviewer,\n                language: currentBuffer.language,\n                filePath: currentBuffer.filePath,\n            })\n        }\n\n        this.props.editorManager.anyEditor.onBufferEnter.subscribe(onEnter => {\n            const previewer = this.props.previewManager.getPreviewer(onEnter.language)\n            this.setState({\n                previewer,\n                language: onEnter.language,\n                filePath: onEnter.filePath,\n            })\n        })\n    }\n\n    public render(): JSX.Element {\n        const element = this.state.previewer\n            ? this.state.previewer.render({\n                  language: this.state.language,\n                  filePath: this.state.filePath,\n              })\n            : null\n\n        return <PreviewWrapper>{element}</PreviewWrapper>\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Preview/index.tsx",
    "content": "/**\n * Preview.tsx\n *\n * Service for registering live-preview providers\n */\n\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\n\nimport { CallbackCommand, CommandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\n\nimport { PreviewBufferLayer } from \"./PreviewBufferLayer\"\n\nexport interface PreviewContext {\n    filePath: string\n    language: string\n}\n\nexport interface IPreviewer {\n    render(previewContext: PreviewContext): JSX.Element\n}\n\nexport interface IdToPreviewer {\n    [id: string]: IPreviewer\n}\nexport interface LanguageToDefaultPreviewer {\n    [id: string]: IPreviewer\n}\n\nexport class NoopPreviewer {\n    public render(previewContext: PreviewContext): JSX.Element {\n        return (\n            <div>\n                <div>no-op previewer for: {previewContext.filePath}</div>\n                <div>language: {previewContext.language}</div>\n            </div>\n        )\n    }\n}\n\nexport class NullPreviewer {\n    public render(previewContext: PreviewContext): JSX.Element {\n        return <div>No previewer registered for this filetype</div>\n    }\n}\n\nexport class Preview {\n    // private _previewers: IdToPreviewer = {}\n    private _defaultPreviewers: LanguageToDefaultPreviewer = {}\n\n    constructor(private _editorManager: EditorManager) {\n        this.registerDefaultPreviewer(\"html\", new NoopPreviewer())\n    }\n\n    public async openPreviewPane(\n        openMode: Oni.FileOpenMode = Oni.FileOpenMode.VerticalSplit,\n    ): Promise<void> {\n        const activeEditor: any = this._editorManager.activeEditor\n        const buf = await activeEditor.openFile(\"PREVIEW\", { openMode })\n        buf.addLayer(new PreviewBufferLayer(this._editorManager, this))\n    }\n\n    public registerDefaultPreviewer(language: string, previewer: IPreviewer): void {\n        this._defaultPreviewers[language] = previewer\n    }\n\n    public getPreviewer(language: string): IPreviewer {\n        if (this._defaultPreviewers[language]) {\n            return this._defaultPreviewers[language]\n        } else {\n            return new NullPreviewer()\n        }\n    }\n}\n\nlet _preview: Preview\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n) => {\n    _preview = new Preview(editorManager)\n\n    if (configuration.getValue(\"experimental.preview.enabled\")) {\n        commandManager.registerCommand(\n            new CallbackCommand(\n                \"preview.open\",\n                \"Preview: Open in Vertical Split\",\n                \"Open preview pane in a vertical split\",\n                () => _preview.openPreviewPane(Oni.FileOpenMode.VerticalSplit),\n            ),\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Recorder.ts",
    "content": "/**\n * Recorder.ts\n *\n * Manages a variety of recording scenarios, including:\n *  - Take & save screenshot\n *  - Record & save video (.webm)\n */\n\nimport { clipboard, desktopCapturer } from \"electron\"\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { configuration } from \"./Configuration\"\nimport { getInstance as getNotificationsInstance } from \"./Notifications\"\n\ndeclare var MediaRecorder: any\n\nconst ONI_RECORDER_TITLE = \"oni_recorder_title\"\n\nconst toBuffer = (ab: ArrayBuffer) => {\n    const buffer = new Buffer(ab.byteLength)\n    const arr = new Uint8Array(ab)\n    for (let i = 0; i < arr.byteLength; i++) {\n        buffer[i] = arr[i]\n    }\n    return buffer\n}\n\nclass Recorder implements Oni.Recorder {\n    private _recorder: any = null\n    private _blobs: Blob[] = []\n\n    public startRecording(): void {\n        const title = document.title\n        document.title = ONI_RECORDER_TITLE\n\n        desktopCapturer.getSources({ types: [\"window\", \"screen\"] }, (error, sources) => {\n            if (error) {\n                throw error\n            }\n            // tslint:disable-next-line prefer-for-of\n            for (let i = 0; i < sources.length; i++) {\n                const src = sources[i]\n                if (src.name === ONI_RECORDER_TITLE) {\n                    document.title = title\n\n                    const size = getDimensions()\n                    // tslint:disable-next-line no-string-literal\n                    navigator[\"webkitGetUserMedia\"](\n                        {\n                            audio: false,\n                            video: {\n                                mandatory: {\n                                    chromeMediaSource: \"desktop\",\n                                    chromeMediaSourceId: src.id,\n                                    minWidth: 320,\n                                    maxWidth: size.width,\n                                    minHeight: 240,\n                                    maxHeight: size.height,\n                                },\n                            },\n                        },\n                        (stream: any) => {\n                            this._handleStream(stream)\n                        },\n                        (err: Error) => {\n                            this._handleUserMediaError(err)\n                        },\n                    )\n                    return\n                }\n            }\n        })\n    }\n\n    public get isRecording(): boolean {\n        return !!this._recorder\n    }\n\n    public async stopRecording(fileName?: string): Promise<void> {\n        this._recorder.stop()\n\n        const arrayBuffer = await toArrayBuffer(new Blob(this._blobs, { type: \"video/webm\" }))\n\n        const buffer = toBuffer(arrayBuffer)\n        fileName = fileName || getFileName(\"oni-video\", \"webm\")\n        const videoFilePath = getOutputPath(fileName)\n\n        // TODO: Finish making this async\n        if (fs.existsSync(videoFilePath)) {\n            fs.unlinkSync(videoFilePath)\n        }\n\n        fs.writeFileSync(videoFilePath, buffer)\n\n        this._recorder = null\n        this._blobs = []\n\n        const notification = getNotificationsInstance().createItem()\n        notification.setContents(\"Recording finished\", \"Recording saved to: \" + videoFilePath)\n        notification.setLevel(\"success\")\n        notification.show()\n    }\n\n    public takeScreenshot(fileName?: string, scale: number = 1): void {\n        const webContents = require(\"electron\").remote.getCurrentWebContents()\n        webContents.capturePage(image => {\n            const pngBuffer = image.toPNG({ scaleFactor: scale })\n\n            fileName = fileName || getFileName(\"oni-screenshot\", \"png\")\n            const screenshotPath = getOutputPath(fileName)\n            fs.writeFileSync(screenshotPath, pngBuffer)\n            if (configuration.getValue(\"recorder.copyScreenshotToClipboard\")) {\n                clipboard.writeImage(screenshotPath as any)\n            }\n\n            const notification = getNotificationsInstance().createItem()\n            notification.setContents(\"Screenshot taken\", \"Screenshot saved to \" + screenshotPath)\n            notification.setLevel(\"success\")\n            notification.show()\n        })\n    }\n\n    private _handleStream(stream: any) {\n        this._recorder = new MediaRecorder(stream)\n        this._blobs = []\n        this._recorder.ondataavailable = (evt: any) => {\n            this._blobs.push(evt.data)\n        }\n        this._recorder.start(100 /* ms */)\n    }\n\n    private _handleUserMediaError(err: Error) {\n        Log.error(err)\n    }\n}\n\n// Some of this code was adapted and modified from this stackoverflow post:\n// https://stackoverflow.com/questions/36753288/saving-desktopcapturer-to-video-file-in-electron\nconst toArrayBuffer = async (blob: Blob): Promise<ArrayBuffer> => {\n    return new Promise<ArrayBuffer>((resolve, reject) => {\n        const fileReader = new FileReader()\n        fileReader.onload = evt => {\n            const arrayBuffer = fileReader.result as ArrayBuffer\n            resolve(arrayBuffer)\n        }\n        fileReader.readAsArrayBuffer(blob)\n    })\n}\n\nconst getDimensions = () => {\n    const size = require(\"electron\")\n        .remote.getCurrentWindow()\n        .getSize()\n    return {\n        width: size[0],\n        height: size[1],\n    }\n}\n\nconst getFileName = (fileBase: string, fileExtension: string) => {\n    return `${fileBase}-${new Date().getTime()}.${fileExtension}`\n}\n\nconst getOutputPath = (fileName: string) => {\n    const outputPath = configuration.getValue(\"recorder.outputPath\")\n    return path.join(outputPath, fileName)\n}\n\nexport const recorder = new Recorder()\n"
  },
  {
    "path": "browser/src/Services/Search/FinderProcess.ts",
    "content": "/**\n * FinderProcess.ts\n *\n * Manages communication with the external finder process\n */\n\nimport { ChildProcess, spawn } from \"child_process\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as Log from \"oni-core-logging\"\nimport { getInstance } from \"./../Workspace\"\n\nexport class FinderProcess {\n    private _process: ChildProcess\n\n    private _lastData: string = \"\"\n\n    private _onData = new Event<string[]>()\n    private _onError = new Event<string>()\n    private _onComplete = new Event<void>()\n    private _workspace = getInstance()\n\n    public get onData(): IEvent<string[]> {\n        return this._onData\n    }\n\n    public get onComplete(): IEvent<void> {\n        return this._onComplete\n    }\n\n    constructor(private _command: string, private _splitCharacter: string) {}\n\n    public start(): void {\n        if (this._process) {\n            return\n        }\n\n        if (Log.isDebugLoggingEnabled()) {\n            Log.debug(\n                \"[FinderProcess::start] Starting finder process with this command: \" +\n                    this._command,\n            )\n        }\n\n        this._process = spawn(this._command, [], {\n            shell: true,\n            cwd: this._workspace.activeWorkspace,\n        })\n        this._process.stdout.on(\"data\", data => {\n            const { didExtract, remnant, splitData } = extractSplitData(\n                data,\n                this._splitCharacter,\n                this._lastData,\n            )\n\n            if (!didExtract) {\n                return\n            }\n\n            this._lastData = remnant\n\n            this._onData.dispatch(splitData)\n        })\n\n        this._process.stderr.on(\"data\", data => {\n            this._onError.dispatch(data.toString())\n        })\n\n        this._process.on(\"exit\", code => {\n            this._onComplete.dispatch()\n        })\n    }\n\n    public stop(): void {\n        this._process.kill()\n    }\n}\n\nexport const extractSplitData = (\n    data: string | Buffer,\n    splitCharacter: string,\n    lastRemnant: string,\n) => {\n    if (!data) {\n        return {\n            didExtract: false,\n            remnant: \"\",\n            splitData: [],\n        }\n    }\n\n    const dataString = lastRemnant + data.toString()\n    const isCleanEnd = dataString.endsWith(splitCharacter)\n    const splitData = dataString.split(splitCharacter)\n\n    let remnant = \"\"\n\n    if (!isCleanEnd) {\n        remnant = splitData.pop()\n    } else {\n        // split leaves behind an empty string in the array if the string to split ends with the delimiter\n        splitData.splice(-1, 1)\n    }\n\n    return { didExtract: true, remnant, splitData }\n}\n"
  },
  {
    "path": "browser/src/Services/Search/RipGrep.ts",
    "content": "/**\n * RipGrep.ts\n *\n * Gets command / arguments for packaged ripgrep command\n */\n\nimport * as path from \"path\"\n\nimport * as Platform from \"./../../Platform\"\n\nexport function getCommand(): string {\n    const rootPath = path.join(__dirname, \"node_modules\", \"oni-ripgrep\", \"bin\")\n    const executableName = Platform.isWindows() ? \"rg.exe\" : \"rg\"\n\n    // Wrap in quotes in case there are spaces in the path\n    return '\"' + path.join(rootPath, executableName) + '\"'\n}\n\nexport function getArguments(excludePaths: string[], shouldShowHidden: boolean): string[] {\n    const ignoreArguments = excludePaths.reduce((prev, cur) => {\n        return prev.concat([\"-g\", \"!\" + cur])\n    }, [])\n\n    const showHidden = shouldShowHidden ? [\"--hidden\"] : []\n\n    return [\"--vimgrep\"].concat(showHidden, ignoreArguments)\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/CharCode.ts",
    "content": "/* tslint:disable */\n/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\"use strict\"\n\n// Names from https://blog.codinghorror.com/ascii-pronunciation-rules-for-programmers/\n\n/**\n * An inlined enum containing useful character codes (to be used with String.charCodeAt).\n * Please leave the const keyword such that it gets inlined when compiled to JavaScript!\n */\nexport const enum CharCode {\n    Null = 0,\n    /**\n     * The `\\t` character.\n     */\n    Tab = 9,\n    /**\n     * The `\\n` character.\n     */\n    LineFeed = 10,\n    /**\n     * The `\\r` character.\n     */\n    CarriageReturn = 13,\n    Space = 32,\n    /**\n     * The `!` character.\n     */\n    ExclamationMark = 33,\n    /**\n     * The `\"` character.\n     */\n    DoubleQuote = 34,\n    /**\n     * The `#` character.\n     */\n    Hash = 35,\n    /**\n     * The `$` character.\n     */\n    DollarSign = 36,\n    /**\n     * The `%` character.\n     */\n    PercentSign = 37,\n    /**\n     * The `&` character.\n     */\n    Ampersand = 38,\n    /**\n     * The `'` character.\n     */\n    SingleQuote = 39,\n    /**\n     * The `(` character.\n     */\n    OpenParen = 40,\n    /**\n     * The `)` character.\n     */\n    CloseParen = 41,\n    /**\n     * The `*` character.\n     */\n    Asterisk = 42,\n    /**\n     * The `+` character.\n     */\n    Plus = 43,\n    /**\n     * The `,` character.\n     */\n    Comma = 44,\n    /**\n     * The `-` character.\n     */\n    Dash = 45,\n    /**\n     * The `.` character.\n     */\n    Period = 46,\n    /**\n     * The `/` character.\n     */\n    Slash = 47,\n\n    Digit0 = 48,\n    Digit1 = 49,\n    Digit2 = 50,\n    Digit3 = 51,\n    Digit4 = 52,\n    Digit5 = 53,\n    Digit6 = 54,\n    Digit7 = 55,\n    Digit8 = 56,\n    Digit9 = 57,\n\n    /**\n     * The `:` character.\n     */\n    Colon = 58,\n    /**\n     * The `;` character.\n     */\n    Semicolon = 59,\n    /**\n     * The `<` character.\n     */\n    LessThan = 60,\n    /**\n     * The `=` character.\n     */\n    Equals = 61,\n    /**\n     * The `>` character.\n     */\n    GreaterThan = 62,\n    /**\n     * The `?` character.\n     */\n    QuestionMark = 63,\n    /**\n     * The `@` character.\n     */\n    AtSign = 64,\n\n    A = 65,\n    B = 66,\n    C = 67,\n    D = 68,\n    E = 69,\n    F = 70,\n    G = 71,\n    H = 72,\n    I = 73,\n    J = 74,\n    K = 75,\n    L = 76,\n    M = 77,\n    N = 78,\n    O = 79,\n    P = 80,\n    Q = 81,\n    R = 82,\n    S = 83,\n    T = 84,\n    U = 85,\n    V = 86,\n    W = 87,\n    X = 88,\n    Y = 89,\n    Z = 90,\n\n    /**\n     * The `[` character.\n     */\n    OpenSquareBracket = 91,\n    /**\n     * The `\\` character.\n     */\n    Backslash = 92,\n    /**\n     * The `]` character.\n     */\n    CloseSquareBracket = 93,\n    /**\n     * The `^` character.\n     */\n    Caret = 94,\n    /**\n     * The `_` character.\n     */\n    Underline = 95,\n    /**\n     * The ``(`)`` character.\n     */\n    BackTick = 96,\n\n    a = 97,\n    b = 98,\n    c = 99,\n    d = 100,\n    e = 101,\n    f = 102,\n    g = 103,\n    h = 104,\n    i = 105,\n    j = 106,\n    k = 107,\n    l = 108,\n    m = 109,\n    n = 110,\n    o = 111,\n    p = 112,\n    q = 113,\n    r = 114,\n    s = 115,\n    t = 116,\n    u = 117,\n    v = 118,\n    w = 119,\n    x = 120,\n    y = 121,\n    z = 122,\n\n    /**\n     * The `{` character.\n     */\n    OpenCurlyBrace = 123,\n    /**\n     * The `|` character.\n     */\n    Pipe = 124,\n    /**\n     * The `}` character.\n     */\n    CloseCurlyBrace = 125,\n    /**\n     * The `~` character.\n     */\n    Tilde = 126,\n\n    U_Combining_Grave_Accent = 0x0300, //\tU+0300\tCombining Grave Accent\n    U_Combining_Acute_Accent = 0x0301, //\tU+0301\tCombining Acute Accent\n    U_Combining_Circumflex_Accent = 0x0302, //\tU+0302\tCombining Circumflex Accent\n    U_Combining_Tilde = 0x0303, //\tU+0303\tCombining Tilde\n    U_Combining_Macron = 0x0304, //\tU+0304\tCombining Macron\n    U_Combining_Overline = 0x0305, //\tU+0305\tCombining Overline\n    U_Combining_Breve = 0x0306, //\tU+0306\tCombining Breve\n    U_Combining_Dot_Above = 0x0307, //\tU+0307\tCombining Dot Above\n    U_Combining_Diaeresis = 0x0308, //\tU+0308\tCombining Diaeresis\n    U_Combining_Hook_Above = 0x0309, //\tU+0309\tCombining Hook Above\n    U_Combining_Ring_Above = 0x030a, //\tU+030A\tCombining Ring Above\n    U_Combining_Double_Acute_Accent = 0x030b, //\tU+030B\tCombining Double Acute Accent\n    U_Combining_Caron = 0x030c, //\tU+030C\tCombining Caron\n    U_Combining_Vertical_Line_Above = 0x030d, //\tU+030D\tCombining Vertical Line Above\n    U_Combining_Double_Vertical_Line_Above = 0x030e, //\tU+030E\tCombining Double Vertical Line Above\n    U_Combining_Double_Grave_Accent = 0x030f, //\tU+030F\tCombining Double Grave Accent\n    U_Combining_Candrabindu = 0x0310, //\tU+0310\tCombining Candrabindu\n    U_Combining_Inverted_Breve = 0x0311, //\tU+0311\tCombining Inverted Breve\n    U_Combining_Turned_Comma_Above = 0x0312, //\tU+0312\tCombining Turned Comma Above\n    U_Combining_Comma_Above = 0x0313, //\tU+0313\tCombining Comma Above\n    U_Combining_Reversed_Comma_Above = 0x0314, //\tU+0314\tCombining Reversed Comma Above\n    U_Combining_Comma_Above_Right = 0x0315, //\tU+0315\tCombining Comma Above Right\n    U_Combining_Grave_Accent_Below = 0x0316, //\tU+0316\tCombining Grave Accent Below\n    U_Combining_Acute_Accent_Below = 0x0317, //\tU+0317\tCombining Acute Accent Below\n    U_Combining_Left_Tack_Below = 0x0318, //\tU+0318\tCombining Left Tack Below\n    U_Combining_Right_Tack_Below = 0x0319, //\tU+0319\tCombining Right Tack Below\n    U_Combining_Left_Angle_Above = 0x031a, //\tU+031A\tCombining Left Angle Above\n    U_Combining_Horn = 0x031b, //\tU+031B\tCombining Horn\n    U_Combining_Left_Half_Ring_Below = 0x031c, //\tU+031C\tCombining Left Half Ring Below\n    U_Combining_Up_Tack_Below = 0x031d, //\tU+031D\tCombining Up Tack Below\n    U_Combining_Down_Tack_Below = 0x031e, //\tU+031E\tCombining Down Tack Below\n    U_Combining_Plus_Sign_Below = 0x031f, //\tU+031F\tCombining Plus Sign Below\n    U_Combining_Minus_Sign_Below = 0x0320, //\tU+0320\tCombining Minus Sign Below\n    U_Combining_Palatalized_Hook_Below = 0x0321, //\tU+0321\tCombining Palatalized Hook Below\n    U_Combining_Retroflex_Hook_Below = 0x0322, //\tU+0322\tCombining Retroflex Hook Below\n    U_Combining_Dot_Below = 0x0323, //\tU+0323\tCombining Dot Below\n    U_Combining_Diaeresis_Below = 0x0324, //\tU+0324\tCombining Diaeresis Below\n    U_Combining_Ring_Below = 0x0325, //\tU+0325\tCombining Ring Below\n    U_Combining_Comma_Below = 0x0326, //\tU+0326\tCombining Comma Below\n    U_Combining_Cedilla = 0x0327, //\tU+0327\tCombining Cedilla\n    U_Combining_Ogonek = 0x0328, //\tU+0328\tCombining Ogonek\n    U_Combining_Vertical_Line_Below = 0x0329, //\tU+0329\tCombining Vertical Line Below\n    U_Combining_Bridge_Below = 0x032a, //\tU+032A\tCombining Bridge Below\n    U_Combining_Inverted_Double_Arch_Below = 0x032b, //\tU+032B\tCombining Inverted Double Arch Below\n    U_Combining_Caron_Below = 0x032c, //\tU+032C\tCombining Caron Below\n    U_Combining_Circumflex_Accent_Below = 0x032d, //\tU+032D\tCombining Circumflex Accent Below\n    U_Combining_Breve_Below = 0x032e, //\tU+032E\tCombining Breve Below\n    U_Combining_Inverted_Breve_Below = 0x032f, //\tU+032F\tCombining Inverted Breve Below\n    U_Combining_Tilde_Below = 0x0330, //\tU+0330\tCombining Tilde Below\n    U_Combining_Macron_Below = 0x0331, //\tU+0331\tCombining Macron Below\n    U_Combining_Low_Line = 0x0332, //\tU+0332\tCombining Low Line\n    U_Combining_Double_Low_Line = 0x0333, //\tU+0333\tCombining Double Low Line\n    U_Combining_Tilde_Overlay = 0x0334, //\tU+0334\tCombining Tilde Overlay\n    U_Combining_Short_Stroke_Overlay = 0x0335, //\tU+0335\tCombining Short Stroke Overlay\n    U_Combining_Long_Stroke_Overlay = 0x0336, //\tU+0336\tCombining Long Stroke Overlay\n    U_Combining_Short_Solidus_Overlay = 0x0337, //\tU+0337\tCombining Short Solidus Overlay\n    U_Combining_Long_Solidus_Overlay = 0x0338, //\tU+0338\tCombining Long Solidus Overlay\n    U_Combining_Right_Half_Ring_Below = 0x0339, //\tU+0339\tCombining Right Half Ring Below\n    U_Combining_Inverted_Bridge_Below = 0x033a, //\tU+033A\tCombining Inverted Bridge Below\n    U_Combining_Square_Below = 0x033b, //\tU+033B\tCombining Square Below\n    U_Combining_Seagull_Below = 0x033c, //\tU+033C\tCombining Seagull Below\n    U_Combining_X_Above = 0x033d, //\tU+033D\tCombining X Above\n    U_Combining_Vertical_Tilde = 0x033e, //\tU+033E\tCombining Vertical Tilde\n    U_Combining_Double_Overline = 0x033f, //\tU+033F\tCombining Double Overline\n    U_Combining_Grave_Tone_Mark = 0x0340, //\tU+0340\tCombining Grave Tone Mark\n    U_Combining_Acute_Tone_Mark = 0x0341, //\tU+0341\tCombining Acute Tone Mark\n    U_Combining_Greek_Perispomeni = 0x0342, //\tU+0342\tCombining Greek Perispomeni\n    U_Combining_Greek_Koronis = 0x0343, //\tU+0343\tCombining Greek Koronis\n    U_Combining_Greek_Dialytika_Tonos = 0x0344, //\tU+0344\tCombining Greek Dialytika Tonos\n    U_Combining_Greek_Ypogegrammeni = 0x0345, //\tU+0345\tCombining Greek Ypogegrammeni\n    U_Combining_Bridge_Above = 0x0346, //\tU+0346\tCombining Bridge Above\n    U_Combining_Equals_Sign_Below = 0x0347, //\tU+0347\tCombining Equals Sign Below\n    U_Combining_Double_Vertical_Line_Below = 0x0348, //\tU+0348\tCombining Double Vertical Line Below\n    U_Combining_Left_Angle_Below = 0x0349, //\tU+0349\tCombining Left Angle Below\n    U_Combining_Not_Tilde_Above = 0x034a, //\tU+034A\tCombining Not Tilde Above\n    U_Combining_Homothetic_Above = 0x034b, //\tU+034B\tCombining Homothetic Above\n    U_Combining_Almost_Equal_To_Above = 0x034c, //\tU+034C\tCombining Almost Equal To Above\n    U_Combining_Left_Right_Arrow_Below = 0x034d, //\tU+034D\tCombining Left Right Arrow Below\n    U_Combining_Upwards_Arrow_Below = 0x034e, //\tU+034E\tCombining Upwards Arrow Below\n    U_Combining_Grapheme_Joiner = 0x034f, //\tU+034F\tCombining Grapheme Joiner\n    U_Combining_Right_Arrowhead_Above = 0x0350, //\tU+0350\tCombining Right Arrowhead Above\n    U_Combining_Left_Half_Ring_Above = 0x0351, //\tU+0351\tCombining Left Half Ring Above\n    U_Combining_Fermata = 0x0352, //\tU+0352\tCombining Fermata\n    U_Combining_X_Below = 0x0353, //\tU+0353\tCombining X Below\n    U_Combining_Left_Arrowhead_Below = 0x0354, //\tU+0354\tCombining Left Arrowhead Below\n    U_Combining_Right_Arrowhead_Below = 0x0355, //\tU+0355\tCombining Right Arrowhead Below\n    U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below = 0x0356, //\tU+0356\tCombining Right Arrowhead And Up Arrowhead Below\n    U_Combining_Right_Half_Ring_Above = 0x0357, //\tU+0357\tCombining Right Half Ring Above\n    U_Combining_Dot_Above_Right = 0x0358, //\tU+0358\tCombining Dot Above Right\n    U_Combining_Asterisk_Below = 0x0359, //\tU+0359\tCombining Asterisk Below\n    U_Combining_Double_Ring_Below = 0x035a, //\tU+035A\tCombining Double Ring Below\n    U_Combining_Zigzag_Above = 0x035b, //\tU+035B\tCombining Zigzag Above\n    U_Combining_Double_Breve_Below = 0x035c, //\tU+035C\tCombining Double Breve Below\n    U_Combining_Double_Breve = 0x035d, //\tU+035D\tCombining Double Breve\n    U_Combining_Double_Macron = 0x035e, //\tU+035E\tCombining Double Macron\n    U_Combining_Double_Macron_Below = 0x035f, //\tU+035F\tCombining Double Macron Below\n    U_Combining_Double_Tilde = 0x0360, //\tU+0360\tCombining Double Tilde\n    U_Combining_Double_Inverted_Breve = 0x0361, //\tU+0361\tCombining Double Inverted Breve\n    U_Combining_Double_Rightwards_Arrow_Below = 0x0362, //\tU+0362\tCombining Double Rightwards Arrow Below\n    U_Combining_Latin_Small_Letter_A = 0x0363, //\tU+0363\tCombining Latin Small Letter A\n    U_Combining_Latin_Small_Letter_E = 0x0364, //\tU+0364\tCombining Latin Small Letter E\n    U_Combining_Latin_Small_Letter_I = 0x0365, //\tU+0365\tCombining Latin Small Letter I\n    U_Combining_Latin_Small_Letter_O = 0x0366, //\tU+0366\tCombining Latin Small Letter O\n    U_Combining_Latin_Small_Letter_U = 0x0367, //\tU+0367\tCombining Latin Small Letter U\n    U_Combining_Latin_Small_Letter_C = 0x0368, //\tU+0368\tCombining Latin Small Letter C\n    U_Combining_Latin_Small_Letter_D = 0x0369, //\tU+0369\tCombining Latin Small Letter D\n    U_Combining_Latin_Small_Letter_H = 0x036a, //\tU+036A\tCombining Latin Small Letter H\n    U_Combining_Latin_Small_Letter_M = 0x036b, //\tU+036B\tCombining Latin Small Letter M\n    U_Combining_Latin_Small_Letter_R = 0x036c, //\tU+036C\tCombining Latin Small Letter R\n    U_Combining_Latin_Small_Letter_T = 0x036d, //\tU+036D\tCombining Latin Small Letter T\n    U_Combining_Latin_Small_Letter_V = 0x036e, //\tU+036E\tCombining Latin Small Letter V\n    U_Combining_Latin_Small_Letter_X = 0x036f, //\tU+036F\tCombining Latin Small Letter X\n\n    /**\n     * Unicode Character 'LINE SEPARATOR' (U+2028)\n     * http://www.fileformat.info/info/unicode/char/2028/index.htm\n     */\n    LINE_SEPARATOR_2028 = 8232,\n\n    // http://www.fileformat.info/info/unicode/category/Sk/list.htm\n    U_CIRCUMFLEX = 0x005e, // U+005E\tCIRCUMFLEX\n    U_GRAVE_ACCENT = 0x0060, // U+0060\tGRAVE ACCENT\n    U_DIAERESIS = 0x00a8, // U+00A8\tDIAERESIS\n    U_MACRON = 0x00af, // U+00AF\tMACRON\n    U_ACUTE_ACCENT = 0x00b4, // U+00B4\tACUTE ACCENT\n    U_CEDILLA = 0x00b8, // U+00B8\tCEDILLA\n    U_MODIFIER_LETTER_LEFT_ARROWHEAD = 0x02c2, // U+02C2\tMODIFIER LETTER LEFT ARROWHEAD\n    U_MODIFIER_LETTER_RIGHT_ARROWHEAD = 0x02c3, // U+02C3\tMODIFIER LETTER RIGHT ARROWHEAD\n    U_MODIFIER_LETTER_UP_ARROWHEAD = 0x02c4, // U+02C4\tMODIFIER LETTER UP ARROWHEAD\n    U_MODIFIER_LETTER_DOWN_ARROWHEAD = 0x02c5, // U+02C5\tMODIFIER LETTER DOWN ARROWHEAD\n    U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING = 0x02d2, // U+02D2\tMODIFIER LETTER CENTRED RIGHT HALF RING\n    U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING = 0x02d3, // U+02D3\tMODIFIER LETTER CENTRED LEFT HALF RING\n    U_MODIFIER_LETTER_UP_TACK = 0x02d4, // U+02D4\tMODIFIER LETTER UP TACK\n    U_MODIFIER_LETTER_DOWN_TACK = 0x02d5, // U+02D5\tMODIFIER LETTER DOWN TACK\n    U_MODIFIER_LETTER_PLUS_SIGN = 0x02d6, // U+02D6\tMODIFIER LETTER PLUS SIGN\n    U_MODIFIER_LETTER_MINUS_SIGN = 0x02d7, // U+02D7\tMODIFIER LETTER MINUS SIGN\n    U_BREVE = 0x02d8, // U+02D8\tBREVE\n    U_DOT_ABOVE = 0x02d9, // U+02D9\tDOT ABOVE\n    U_RING_ABOVE = 0x02da, // U+02DA\tRING ABOVE\n    U_OGONEK = 0x02db, // U+02DB\tOGONEK\n    U_SMALL_TILDE = 0x02dc, // U+02DC\tSMALL TILDE\n    U_DOUBLE_ACUTE_ACCENT = 0x02dd, // U+02DD\tDOUBLE ACUTE ACCENT\n    U_MODIFIER_LETTER_RHOTIC_HOOK = 0x02de, // U+02DE\tMODIFIER LETTER RHOTIC HOOK\n    U_MODIFIER_LETTER_CROSS_ACCENT = 0x02df, // U+02DF\tMODIFIER LETTER CROSS ACCENT\n    U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR = 0x02e5, // U+02E5\tMODIFIER LETTER EXTRA-HIGH TONE BAR\n    U_MODIFIER_LETTER_HIGH_TONE_BAR = 0x02e6, // U+02E6\tMODIFIER LETTER HIGH TONE BAR\n    U_MODIFIER_LETTER_MID_TONE_BAR = 0x02e7, // U+02E7\tMODIFIER LETTER MID TONE BAR\n    U_MODIFIER_LETTER_LOW_TONE_BAR = 0x02e8, // U+02E8\tMODIFIER LETTER LOW TONE BAR\n    U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR = 0x02e9, // U+02E9\tMODIFIER LETTER EXTRA-LOW TONE BAR\n    U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK = 0x02ea, // U+02EA\tMODIFIER LETTER YIN DEPARTING TONE MARK\n    U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK = 0x02eb, // U+02EB\tMODIFIER LETTER YANG DEPARTING TONE MARK\n    U_MODIFIER_LETTER_UNASPIRATED = 0x02ed, // U+02ED\tMODIFIER LETTER UNASPIRATED\n    U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD = 0x02ef, // U+02EF\tMODIFIER LETTER LOW DOWN ARROWHEAD\n    U_MODIFIER_LETTER_LOW_UP_ARROWHEAD = 0x02f0, // U+02F0\tMODIFIER LETTER LOW UP ARROWHEAD\n    U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD = 0x02f1, // U+02F1\tMODIFIER LETTER LOW LEFT ARROWHEAD\n    U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD = 0x02f2, // U+02F2\tMODIFIER LETTER LOW RIGHT ARROWHEAD\n    U_MODIFIER_LETTER_LOW_RING = 0x02f3, // U+02F3\tMODIFIER LETTER LOW RING\n    U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT = 0x02f4, // U+02F4\tMODIFIER LETTER MIDDLE GRAVE ACCENT\n    U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT = 0x02f5, // U+02F5\tMODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT\n    U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT = 0x02f6, // U+02F6\tMODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT\n    U_MODIFIER_LETTER_LOW_TILDE = 0x02f7, // U+02F7\tMODIFIER LETTER LOW TILDE\n    U_MODIFIER_LETTER_RAISED_COLON = 0x02f8, // U+02F8\tMODIFIER LETTER RAISED COLON\n    U_MODIFIER_LETTER_BEGIN_HIGH_TONE = 0x02f9, // U+02F9\tMODIFIER LETTER BEGIN HIGH TONE\n    U_MODIFIER_LETTER_END_HIGH_TONE = 0x02fa, // U+02FA\tMODIFIER LETTER END HIGH TONE\n    U_MODIFIER_LETTER_BEGIN_LOW_TONE = 0x02fb, // U+02FB\tMODIFIER LETTER BEGIN LOW TONE\n    U_MODIFIER_LETTER_END_LOW_TONE = 0x02fc, // U+02FC\tMODIFIER LETTER END LOW TONE\n    U_MODIFIER_LETTER_SHELF = 0x02fd, // U+02FD\tMODIFIER LETTER SHELF\n    U_MODIFIER_LETTER_OPEN_SHELF = 0x02fe, // U+02FE\tMODIFIER LETTER OPEN SHELF\n    U_MODIFIER_LETTER_LOW_LEFT_ARROW = 0x02ff, // U+02FF\tMODIFIER LETTER LOW LEFT ARROW\n    U_GREEK_LOWER_NUMERAL_SIGN = 0x0375, // U+0375\tGREEK LOWER NUMERAL SIGN\n    U_GREEK_TONOS = 0x0384, // U+0384\tGREEK TONOS\n    U_GREEK_DIALYTIKA_TONOS = 0x0385, // U+0385\tGREEK DIALYTIKA TONOS\n    U_GREEK_KORONIS = 0x1fbd, // U+1FBD\tGREEK KORONIS\n    U_GREEK_PSILI = 0x1fbf, // U+1FBF\tGREEK PSILI\n    U_GREEK_PERISPOMENI = 0x1fc0, // U+1FC0\tGREEK PERISPOMENI\n    U_GREEK_DIALYTIKA_AND_PERISPOMENI = 0x1fc1, // U+1FC1\tGREEK DIALYTIKA AND PERISPOMENI\n    U_GREEK_PSILI_AND_VARIA = 0x1fcd, // U+1FCD\tGREEK PSILI AND VARIA\n    U_GREEK_PSILI_AND_OXIA = 0x1fce, // U+1FCE\tGREEK PSILI AND OXIA\n    U_GREEK_PSILI_AND_PERISPOMENI = 0x1fcf, // U+1FCF\tGREEK PSILI AND PERISPOMENI\n    U_GREEK_DASIA_AND_VARIA = 0x1fdd, // U+1FDD\tGREEK DASIA AND VARIA\n    U_GREEK_DASIA_AND_OXIA = 0x1fde, // U+1FDE\tGREEK DASIA AND OXIA\n    U_GREEK_DASIA_AND_PERISPOMENI = 0x1fdf, // U+1FDF\tGREEK DASIA AND PERISPOMENI\n    U_GREEK_DIALYTIKA_AND_VARIA = 0x1fed, // U+1FED\tGREEK DIALYTIKA AND VARIA\n    U_GREEK_DIALYTIKA_AND_OXIA = 0x1fee, // U+1FEE\tGREEK DIALYTIKA AND OXIA\n    U_GREEK_VARIA = 0x1fef, // U+1FEF\tGREEK VARIA\n    U_GREEK_OXIA = 0x1ffd, // U+1FFD\tGREEK OXIA\n    U_GREEK_DASIA = 0x1ffe, // U+1FFE\tGREEK DASIA\n\n    U_OVERLINE = 0x203e, // Unicode Character 'OVERLINE'\n\n    /**\n     * UTF-8 BOM\n     * Unicode Character 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF)\n     * http://www.fileformat.info/info/unicode/char/feff/index.htm\n     */\n    UTF8_BOM = 65279,\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/Comparers.ts",
    "content": "/* tslint:disable */\n/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\"use strict\"\n\nimport { nativeSep } from \"./Utilities\"\n\nlet intlFileNameCollator: Intl.Collator\nlet intlFileNameCollatorIsNumeric: boolean\n\nexport function setFileNameComparer(collator: Intl.Collator): void {\n    intlFileNameCollator = collator\n    intlFileNameCollatorIsNumeric = collator.resolvedOptions().numeric\n}\n\nexport function compareFileNames(one: string, other: string, caseSensitive = false): number {\n    if (intlFileNameCollator) {\n        const a = one || \"\"\n        const b = other || \"\"\n        const result = intlFileNameCollator.compare(a, b)\n\n        // Using the numeric option in the collator will\n        // make compare(`foo1`, `foo01`) === 0. We must disambiguate.\n        if (intlFileNameCollatorIsNumeric && result === 0 && a !== b) {\n            return a < b ? -1 : 1\n        }\n\n        return result\n    }\n\n    return noIntlCompareFileNames(one, other, caseSensitive)\n}\n\nconst FileNameMatch = /^(.*?)(\\.([^.]*))?$/\n\nexport function noIntlCompareFileNames(one: string, other: string, caseSensitive = false): number {\n    if (!caseSensitive) {\n        one = one && one.toLowerCase()\n        other = other && other.toLowerCase()\n    }\n\n    const [oneName, oneExtension] = extractNameAndExtension(one)\n    const [otherName, otherExtension] = extractNameAndExtension(other)\n\n    if (oneName !== otherName) {\n        return oneName < otherName ? -1 : 1\n    }\n\n    if (oneExtension === otherExtension) {\n        return 0\n    }\n\n    return oneExtension < otherExtension ? -1 : 1\n}\n\nexport function compareFileExtensions(one: string, other: string): number {\n    if (intlFileNameCollator) {\n        const [oneName, oneExtension] = extractNameAndExtension(one)\n        const [otherName, otherExtension] = extractNameAndExtension(other)\n\n        let result = intlFileNameCollator.compare(oneExtension, otherExtension)\n\n        if (result === 0) {\n            // Using the numeric option in the collator will\n            // make compare(`foo1`, `foo01`) === 0. We must disambiguate.\n            if (intlFileNameCollatorIsNumeric && oneExtension !== otherExtension) {\n                return oneExtension < otherExtension ? -1 : 1\n            }\n\n            // Extensions are equal, compare filenames\n            result = intlFileNameCollator.compare(oneName, otherName)\n\n            if (intlFileNameCollatorIsNumeric && result === 0 && oneName !== otherName) {\n                return oneName < otherName ? -1 : 1\n            }\n        }\n\n        return result\n    }\n\n    return noIntlCompareFileExtensions(one, other)\n}\n\nfunction noIntlCompareFileExtensions(one: string, other: string): number {\n    const [oneName, oneExtension] = extractNameAndExtension(one && one.toLowerCase())\n    const [otherName, otherExtension] = extractNameAndExtension(other && other.toLowerCase())\n\n    if (oneExtension !== otherExtension) {\n        return oneExtension < otherExtension ? -1 : 1\n    }\n\n    if (oneName === otherName) {\n        return 0\n    }\n\n    return oneName < otherName ? -1 : 1\n}\n\nfunction extractNameAndExtension(str?: string): [string, string] {\n    const match = str ? FileNameMatch.exec(str) : ([] as RegExpExecArray)\n\n    return [(match && match[1]) || \"\", (match && match[3]) || \"\"]\n}\n\nfunction comparePathComponents(one: string, other: string, caseSensitive = false): number {\n    if (!caseSensitive) {\n        one = one && one.toLowerCase()\n        other = other && other.toLowerCase()\n    }\n\n    if (one === other) {\n        return 0\n    }\n\n    return one < other ? -1 : 1\n}\n\nexport function comparePaths(one: string, other: string, caseSensitive = false): number {\n    const oneParts = one.split(nativeSep)\n    const otherParts = other.split(nativeSep)\n\n    const lastOne = oneParts.length - 1\n    const lastOther = otherParts.length - 1\n    let endOne: boolean, endOther: boolean\n\n    for (let i = 0; ; i++) {\n        endOne = lastOne === i\n        endOther = lastOther === i\n\n        if (endOne && endOther) {\n            return compareFileNames(oneParts[i], otherParts[i], caseSensitive)\n        } else if (endOne) {\n            return -1\n        } else if (endOther) {\n            return 1\n        }\n\n        const result = comparePathComponents(oneParts[i], otherParts[i], caseSensitive)\n\n        if (result !== 0) {\n            return result\n        }\n    }\n}\n\nexport function compareAnything(one: string, other: string, lookFor: string): number {\n    let elementAName = one.toLowerCase()\n    let elementBName = other.toLowerCase()\n\n    // Sort prefix matches over non prefix matches\n    const prefixCompare = compareByPrefix(one, other, lookFor)\n    if (prefixCompare) {\n        return prefixCompare\n    }\n\n    // Sort suffix matches over non suffix matches\n    let elementASuffixMatch = elementAName.endsWith(lookFor)\n    let elementBSuffixMatch = elementBName.endsWith(lookFor)\n    if (elementASuffixMatch !== elementBSuffixMatch) {\n        return elementASuffixMatch ? -1 : 1\n    }\n\n    // Understand file names\n    let r = compareFileNames(elementAName, elementBName)\n    if (r !== 0) {\n        return r\n    }\n\n    // Compare by name\n    return elementAName.localeCompare(elementBName)\n}\n\nexport function compareByPrefix(one: string, other: string, lookFor: string): number {\n    let elementAName = one.toLowerCase()\n    let elementBName = other.toLowerCase()\n\n    // Sort prefix matches over non prefix matches\n    let elementAPrefixMatch = elementAName.startsWith(lookFor)\n    let elementBPrefixMatch = elementBName.startsWith(lookFor)\n    if (elementAPrefixMatch !== elementBPrefixMatch) {\n        return elementAPrefixMatch ? -1 : 1\n    } else if (elementAPrefixMatch && elementBPrefixMatch) {\n        // Same prefix: Sort shorter matches to the top to have those on top that match more precisely\n        if (elementAName.length < elementBName.length) {\n            return -1\n        }\n\n        if (elementAName.length > elementBName.length) {\n            return 1\n        }\n    }\n\n    return 0\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/OniQuickOpenScorer.ts",
    "content": "import { IMatch } from \"./filters\"\nimport {\n    compareItemsByScore,\n    IItemAccessor,\n    IItemScore,\n    prepareQuery,\n    scoreItem,\n    ScorerCache,\n} from \"./QuickOpenScorer\"\nimport { nativeSep } from \"./Utilities\"\n\nexport const NO_ITEM_SCORE: IItemScore = Object.freeze({ score: 0 })\n\nclass OniAccessor implements IItemAccessor<any> {\n    public getItemLabel(result: any): string {\n        return result.label ? result.label : \"\"\n    }\n\n    public getItemDescription(result: any): string {\n        return result.detail ? result.detail : \"\"\n    }\n\n    public getItemPath(result: any): string {\n        return result.detail + nativeSep + result.label\n    }\n}\n\nexport function scoreItemOni(\n    resultObject: any,\n    searchString: string,\n    fuzzy: boolean,\n    cache: ScorerCache,\n): IItemScore {\n    if (!searchString) {\n        return NO_ITEM_SCORE\n    }\n\n    const query = prepareQuery(searchString)\n\n    if (!resultObject || !query.value) {\n        return NO_ITEM_SCORE\n    }\n\n    const accessor = new OniAccessor()\n\n    return scoreItem(resultObject, query, fuzzy, accessor, cache)\n}\n\nexport function compareItemsByScoreOni(\n    resultObjectA: any,\n    resultObjectB: any,\n    searchString: string,\n    fuzzy: boolean,\n    cache: ScorerCache,\n): number {\n    if (!searchString) {\n        return 0\n    }\n\n    const query = prepareQuery(searchString)\n\n    if (!resultObjectA || !resultObjectB || !query.value) {\n        return 0\n    }\n\n    const accessor = new OniAccessor()\n\n    return compareItemsByScore(resultObjectA, resultObjectB, query, fuzzy, accessor, cache)\n}\n\nexport const getHighlightsFromResult = (result: IMatch[]): number[] => {\n    if (!result) {\n        return []\n    }\n\n    const highlights: number[] = []\n\n    result.forEach(r => {\n        for (let i = r.start; i < r.end; i++) {\n            highlights.push(i)\n        }\n    })\n\n    return highlights\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/QuickOpenScorer.ts",
    "content": "/* tslint:disable */\n/*---------------------------------------------------------------------------------------------\n *  Copyright (c) Microsoft Corporation. All rights reserved.\n *  Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n\"use strict\"\n\nimport { CharCode } from \"./CharCode\"\nimport { compareAnything } from \"./Comparers\"\nimport { createMatches, IMatch, matchesCamelCase, matchesPrefix } from \"./filters\"\nimport { equalsIgnoreCase } from \"./strings\"\nimport { isLinux, isWindows, stripWildcards, nativeSep, isUpper } from \"./Utilities\"\n\nexport type Score = [number /* score */, number[] /* match positions */]\nexport type ScorerCache = { [key: string]: IItemScore }\n\nconst NO_MATCH = 0\nconst NO_SCORE: Score = [NO_MATCH, []]\n\n// const DEBUG = false;\n// const DEBUG_MATRIX = false;\n\nexport function score(target: string, query: string, queryLower: string, fuzzy: boolean): Score {\n    if (!target || !query) {\n        return NO_SCORE // return early if target or query are undefined\n    }\n\n    const targetLength = target.length\n    const queryLength = query.length\n\n    if (targetLength < queryLength) {\n        return NO_SCORE // impossible for query to be contained in target\n    }\n\n    // if (DEBUG) {\n    // \tconsole.group(`Target: ${target}, Query: ${query}`);\n    // }\n\n    const targetLower = target.toLowerCase()\n\n    // When not searching fuzzy, we require the query to be contained fully\n    // in the target string contiguously.\n    if (!fuzzy) {\n        const indexOfQueryInTarget = targetLower.indexOf(queryLower)\n        if (indexOfQueryInTarget === -1) {\n            // if (DEBUG) {\n            // \tconsole.log(`Characters not matching consecutively ${queryLower} within ${targetLower}`);\n            // }\n\n            return NO_SCORE\n        }\n    }\n\n    const res = doScore(query, queryLower, queryLength, target, targetLower, targetLength)\n\n    // if (DEBUG) {\n    // \tconsole.log(`%cFinal Score: ${res[0]}`, 'font-weight: bold');\n    // \tconsole.groupEnd();\n    // }\n\n    return res\n}\n\nfunction doScore(\n    query: string,\n    queryLower: string,\n    queryLength: number,\n    target: string,\n    targetLower: string,\n    targetLength: number,\n): [number, number[]] {\n    const scores = []\n    const matches = []\n\n    //\n    // Build Scorer Matrix:\n    //\n    // The matrix is composed of query q and target t. For each index we score\n    // q[i] with t[i] and compare that with the previous score. If the score is\n    // equal or larger, we keep the match. In addition to the score, we also keep\n    // the length of the consecutive matches to use as boost for the score.\n    //\n    //      t   a   r   g   e   t\n    //  q\n    //  u\n    //  e\n    //  r\n    //  y\n    //\n    for (let queryIndex = 0; queryIndex < queryLength; queryIndex++) {\n        for (let targetIndex = 0; targetIndex < targetLength; targetIndex++) {\n            const currentIndex = queryIndex * targetLength + targetIndex\n            const leftIndex = currentIndex - 1\n            const diagIndex = (queryIndex - 1) * targetLength + targetIndex - 1\n\n            const leftScore: number = targetIndex > 0 ? scores[leftIndex] : 0\n            const diagScore: number = queryIndex > 0 && targetIndex > 0 ? scores[diagIndex] : 0\n\n            const matchesSequenceLength: number =\n                queryIndex > 0 && targetIndex > 0 ? matches[diagIndex] : 0\n\n            // If we are not matching on the first query character any more, we only produce a\n            // score if we had a score previously for the last query index (by looking at the diagScore).\n            // This makes sure that the query always matches in sequence on the target. For example\n            // given a target of \"ede\" and a query of \"de\", we would otherwise produce a wrong high score\n            // for query[1] (\"e\") matching on target[0] (\"e\") because of the \"beginning of word\" boost.\n            let score: number\n            if (!diagScore && queryIndex > 0) {\n                score = 0\n            } else {\n                score = computeCharScore(\n                    query,\n                    queryLower,\n                    queryIndex,\n                    target,\n                    targetLower,\n                    targetIndex,\n                    matchesSequenceLength,\n                )\n            }\n\n            // We have a score and its equal or larger than the left score\n            // Match: sequence continues growing from previous diag value\n            // Score: increases by diag score value\n            if (score && diagScore + score >= leftScore) {\n                matches[currentIndex] = matchesSequenceLength + 1\n                scores[currentIndex] = diagScore + score\n            } else {\n                // We either have no score or the score is lower than the left score\n                // Match: reset to 0\n                // Score: pick up from left hand side\n                matches[currentIndex] = NO_MATCH\n                scores[currentIndex] = leftScore\n            }\n        }\n    }\n\n    // Restore Positions (starting from bottom right of matrix)\n    const positions = []\n    let queryIndex = queryLength - 1\n    let targetIndex = targetLength - 1\n    while (queryIndex >= 0 && targetIndex >= 0) {\n        const currentIndex = queryIndex * targetLength + targetIndex\n        const match = matches[currentIndex]\n        if (match === NO_MATCH) {\n            targetIndex-- // go left\n        } else {\n            positions.push(targetIndex)\n\n            // go up and left\n            queryIndex--\n            targetIndex--\n        }\n    }\n\n    // Print matrix\n    // if (DEBUG_MATRIX) {\n    // printMatrix(query, target, matches, scores);\n    // }\n\n    return [scores[queryLength * targetLength - 1], positions.reverse()]\n}\n\nfunction computeCharScore(\n    query: string,\n    queryLower: string,\n    queryIndex: number,\n    target: string,\n    targetLower: string,\n    targetIndex: number,\n    matchesSequenceLength: number,\n): number {\n    let score = 0\n\n    if (queryLower[queryIndex] !== targetLower[targetIndex]) {\n        return score // no match of characters\n    }\n\n    // Character match bonus\n    score += 1\n\n    // if (DEBUG) {\n    // \tconsole.groupCollapsed(`%cCharacter match bonus: +1 (char: ${queryLower[queryIndex]} at index ${targetIndex}, total score: ${score})`, 'font-weight: normal');\n    // }\n\n    // Consecutive match bonus\n    if (matchesSequenceLength > 0) {\n        score += matchesSequenceLength * 5\n\n        // if (DEBUG) {\n        // \tconsole.log('Consecutive match bonus: ' + (matchesSequenceLength * 5));\n        // }\n    }\n\n    // Same case bonus\n    if (query[queryIndex] === target[targetIndex]) {\n        score += 1\n\n        // if (DEBUG) {\n        // \tconsole.log('Same case bonus: +1');\n        // }\n    }\n\n    // Start of word bonus\n    if (targetIndex === 0) {\n        score += 8\n\n        // if (DEBUG) {\n        // \tconsole.log('Start of word bonus: +8');\n        // }\n    } else {\n        // After separator bonus\n        const separatorBonus = scoreSeparatorAtPos(target.charCodeAt(targetIndex - 1))\n        if (separatorBonus) {\n            score += separatorBonus\n\n            // if (DEBUG) {\n            // \tconsole.log('After separtor bonus: +4');\n            // }\n        } else if (isUpper(target.charCodeAt(targetIndex))) {\n            // Inside word upper case bonus (camel case)\n            score += 1\n\n            // if (DEBUG) {\n            // \tconsole.log('Inside word upper case bonus: +1');\n            // }\n        }\n    }\n\n    // if (DEBUG) {\n    // \tconsole.groupEnd();\n    // }\n\n    return score\n}\n\nfunction scoreSeparatorAtPos(charCode: number): number {\n    switch (charCode) {\n        case CharCode.Slash:\n        case CharCode.Backslash:\n            return 5 // prefer path separators...\n        case CharCode.Underline:\n        case CharCode.Dash:\n        case CharCode.Period:\n        case CharCode.Space:\n        case CharCode.SingleQuote:\n        case CharCode.DoubleQuote:\n        case CharCode.Colon:\n            return 4 // ...over other separators\n        default:\n            return 0\n    }\n}\n\n// function printMatrix(query: string, target: string, matches: number[], scores: number[]): void {\n// \tconsole.log('\\t' + target.split('').join('\\t'));\n// \tfor (let queryIndex = 0; queryIndex < query.length; queryIndex++) {\n// \t\tlet line = query[queryIndex] + '\\t';\n// \t\tfor (let targetIndex = 0; targetIndex < target.length; targetIndex++) {\n// \t\t\tconst currentIndex = queryIndex * target.length + targetIndex;\n// \t\t\tline = line + 'M' + matches[currentIndex] + '/' + 'S' + scores[currentIndex] + '\\t';\n// \t\t}\n\n// \t\tconsole.log(line);\n// \t}\n// }\n\n/**\n * Scoring on structural items that have a label and optional description.\n */\nexport interface IItemScore {\n    /**\n     * Overall score.\n     */\n    score: number\n\n    /**\n     * Matches within the label.\n     */\n    labelMatch?: IMatch[]\n\n    /**\n     * Matches within the description.\n     */\n    descriptionMatch?: IMatch[]\n}\n\nconst NO_ITEM_SCORE: IItemScore = Object.freeze({ score: 0 })\n\nexport interface IItemAccessor<T> {\n    /**\n     * Just the label of the item to score on.\n     */\n    getItemLabel(item: T): string\n\n    /**\n     * The optional description of the item to score on. Can be null.\n     */\n    getItemDescription(item: T): string\n\n    /**\n     * If the item is a file, the path of the file to score on. Can be null.\n     */\n    getItemPath(file: T): string\n}\n\nconst PATH_IDENTITY_SCORE = 1 << 18\nconst LABEL_PREFIX_SCORE = 1 << 17\nconst LABEL_CAMELCASE_SCORE = 1 << 16\nconst LABEL_SCORE_THRESHOLD = 1 << 15\n\nexport interface IPreparedQuery {\n    original: string\n    value: string\n    lowercase: string\n    containsPathSeparator: boolean\n}\n\n/**\n * Helper function to prepare a search value for scoring in quick open by removing unwanted characters.\n */\nexport function prepareQuery(original: string): IPreparedQuery {\n    let lowercase: string\n    let containsPathSeparator: boolean\n    let value: string\n\n    if (original) {\n        value = stripWildcards(original).replace(/\\s/g, \"\") // get rid of all wildcards and whitespace\n        if (isWindows) {\n            value = value.replace(/\\//g, nativeSep) // Help Windows users to search for paths when using slash\n        }\n\n        lowercase = value.toLowerCase()\n        containsPathSeparator = value.indexOf(nativeSep) >= 0\n    }\n\n    return { original, value, lowercase, containsPathSeparator }\n}\n\nexport function scoreItem<T>(\n    item: T,\n    query: IPreparedQuery,\n    fuzzy: boolean,\n    accessor: IItemAccessor<T>,\n    cache: ScorerCache,\n): IItemScore {\n    if (!item || !query.value) {\n        return NO_ITEM_SCORE // we need an item and query to score on at least\n    }\n\n    const label = accessor.getItemLabel(item)\n    if (!label) {\n        return NO_ITEM_SCORE // we need a label at least\n    }\n\n    const description = accessor.getItemDescription(item)\n\n    let cacheHash: string\n    if (description) {\n        cacheHash = `${label}${description}${query.value}${fuzzy}`\n    } else {\n        cacheHash = `${label}${query.value}${fuzzy}`\n    }\n\n    const cached = cache[cacheHash]\n    if (cached) {\n        return cached\n    }\n\n    const itemScore = doScoreItem(label, description, accessor.getItemPath(item), query, fuzzy)\n    cache[cacheHash] = itemScore\n\n    return itemScore\n}\n\nfunction doScoreItem(\n    label: string,\n    description: string,\n    path: string,\n    query: IPreparedQuery,\n    fuzzy: boolean,\n): IItemScore {\n    // 1.) treat identity matches on full path highest\n    if (path && isLinux ? query.original === path : equalsIgnoreCase(query.original, path)) {\n        return {\n            score: PATH_IDENTITY_SCORE,\n            labelMatch: [{ start: 0, end: label.length }],\n            descriptionMatch: description ? [{ start: 0, end: description.length }] : void 0,\n        }\n    }\n\n    // We only consider label matches if the query is not including file path separators\n    const preferLabelMatches = !path || !query.containsPathSeparator\n    if (preferLabelMatches) {\n        // 2.) treat prefix matches on the label second highest\n        const prefixLabelMatch = matchesPrefix(query.value, label)\n        if (prefixLabelMatch) {\n            return { score: LABEL_PREFIX_SCORE, labelMatch: prefixLabelMatch }\n        }\n\n        // 3.) treat camelcase matches on the label third highest\n        const camelcaseLabelMatch = matchesCamelCase(query.value, label)\n        if (camelcaseLabelMatch) {\n            return { score: LABEL_CAMELCASE_SCORE, labelMatch: camelcaseLabelMatch }\n        }\n\n        // 4.) prefer scores on the label if any\n        const [labelScore, labelPositions] = score(label, query.value, query.lowercase, fuzzy)\n        if (labelScore) {\n            return {\n                score: labelScore + LABEL_SCORE_THRESHOLD,\n                labelMatch: createMatches(labelPositions),\n            }\n        }\n    }\n\n    // 5.) finally compute description + label scores if we have a description\n    if (description) {\n        let descriptionPrefix = description\n        if (!!path) {\n            descriptionPrefix = `${description}${nativeSep}` // assume this is a file path\n        }\n\n        const descriptionPrefixLength = descriptionPrefix.length\n        const descriptionAndLabel = `${descriptionPrefix}${label}`\n\n        const [labelDescriptionScore, labelDescriptionPositions] = score(\n            descriptionAndLabel,\n            query.value,\n            query.lowercase,\n            fuzzy,\n        )\n        if (labelDescriptionScore) {\n            const labelDescriptionMatches = createMatches(labelDescriptionPositions)\n            const labelMatch: IMatch[] = []\n            const descriptionMatch: IMatch[] = []\n\n            // We have to split the matches back onto the label and description portions\n            labelDescriptionMatches.forEach(h => {\n                // Match overlaps label and description part, we need to split it up\n                if (h.start < descriptionPrefixLength && h.end > descriptionPrefixLength) {\n                    labelMatch.push({ start: 0, end: h.end - descriptionPrefixLength })\n                    descriptionMatch.push({ start: h.start, end: descriptionPrefixLength })\n                } else if (h.start >= descriptionPrefixLength) {\n                    // Match on label part\n                    labelMatch.push({\n                        start: h.start - descriptionPrefixLength,\n                        end: h.end - descriptionPrefixLength,\n                    })\n                } else {\n                    // Match on description part\n                    descriptionMatch.push(h)\n                }\n            })\n\n            return { score: labelDescriptionScore, labelMatch, descriptionMatch }\n        }\n    }\n\n    return NO_ITEM_SCORE\n}\n\nexport function compareItemsByScore<T>(\n    itemA: T,\n    itemB: T,\n    query: IPreparedQuery,\n    fuzzy: boolean,\n    accessor: IItemAccessor<T>,\n    cache: ScorerCache,\n    fallbackComparer = fallbackCompare,\n): number {\n    const itemScoreA = scoreItem(itemA, query, fuzzy, accessor, cache)\n    const itemScoreB = scoreItem(itemB, query, fuzzy, accessor, cache)\n\n    const scoreA = itemScoreA.score\n    const scoreB = itemScoreB.score\n\n    // 1.) prefer identity matches\n    if (scoreA === PATH_IDENTITY_SCORE || scoreB === PATH_IDENTITY_SCORE) {\n        if (scoreA !== scoreB) {\n            return scoreA === PATH_IDENTITY_SCORE ? -1 : 1\n        }\n    }\n\n    // 2.) prefer label prefix matches\n    if (scoreA === LABEL_PREFIX_SCORE || scoreB === LABEL_PREFIX_SCORE) {\n        if (scoreA !== scoreB) {\n            return scoreA === LABEL_PREFIX_SCORE ? -1 : 1\n        }\n\n        const labelA = accessor.getItemLabel(itemA)\n        const labelB = accessor.getItemLabel(itemB)\n\n        // prefer shorter names when both match on label prefix\n        if (labelA.length !== labelB.length) {\n            return labelA.length - labelB.length\n        }\n    }\n\n    // 3.) prefer camelcase matches\n    if (scoreA === LABEL_CAMELCASE_SCORE || scoreB === LABEL_CAMELCASE_SCORE) {\n        if (scoreA !== scoreB) {\n            return scoreA === LABEL_CAMELCASE_SCORE ? -1 : 1\n        }\n\n        const labelA = accessor.getItemLabel(itemA)\n        const labelB = accessor.getItemLabel(itemB)\n\n        // prefer more compact camel case matches over longer\n        const comparedByMatchLength = compareByMatchLength(\n            itemScoreA.labelMatch,\n            itemScoreB.labelMatch,\n        )\n        if (comparedByMatchLength !== 0) {\n            return comparedByMatchLength\n        }\n\n        // prefer shorter names when both match on label camelcase\n        if (labelA.length !== labelB.length) {\n            return labelA.length - labelB.length\n        }\n    }\n\n    // 4.) prefer label scores\n    if (scoreA > LABEL_SCORE_THRESHOLD || scoreB > LABEL_SCORE_THRESHOLD) {\n        if (scoreB < LABEL_SCORE_THRESHOLD) {\n            return -1\n        }\n\n        if (scoreA < LABEL_SCORE_THRESHOLD) {\n            return 1\n        }\n    }\n\n    // 5.) compare by score\n    if (scoreA !== scoreB) {\n        return scoreA > scoreB ? -1 : 1\n    }\n\n    // 6.) scores are identical, prefer more compact matches (label and description)\n    const itemAMatchDistance = computeLabelAndDescriptionMatchDistance(itemA, itemScoreA, accessor)\n    const itemBMatchDistance = computeLabelAndDescriptionMatchDistance(itemB, itemScoreB, accessor)\n    if (itemAMatchDistance && itemBMatchDistance && itemAMatchDistance !== itemBMatchDistance) {\n        return itemBMatchDistance > itemAMatchDistance ? -1 : 1\n    }\n\n    // 7.) at this point, scores are identical and match compactness as well\n    // for both items so we start to use the fallback compare\n    return fallbackComparer(itemA, itemB, query, accessor)\n}\n\nfunction computeLabelAndDescriptionMatchDistance<T>(\n    item: T,\n    score: IItemScore,\n    accessor: IItemAccessor<T>,\n): number {\n    const hasLabelMatches = score.labelMatch && score.labelMatch.length\n    const hasDescriptionMatches = score.descriptionMatch && score.descriptionMatch.length\n\n    let matchStart: number = -1\n    let matchEnd: number = -1\n\n    // If we have description matches, the start is first of description match\n    if (hasDescriptionMatches) {\n        matchStart = score.descriptionMatch[0].start\n    } else if (hasLabelMatches) {\n        // Otherwise, the start is the first label match\n        matchStart = score.labelMatch[0].start\n    }\n\n    // If we have label match, the end is the last label match\n    // If we had a description match, we add the length of the description\n    // as offset to the end to indicate this.\n    if (hasLabelMatches) {\n        matchEnd = score.labelMatch[score.labelMatch.length - 1].end\n        if (hasDescriptionMatches) {\n            const itemDescription = accessor.getItemDescription(item)\n            if (itemDescription) {\n                matchEnd += itemDescription.length\n            }\n        }\n    } else if (hasDescriptionMatches) {\n        // If we have just a description match, the end is the last description match\n        matchEnd = score.descriptionMatch[score.descriptionMatch.length - 1].end\n    }\n\n    return matchEnd - matchStart\n}\n\nfunction compareByMatchLength(matchesA?: IMatch[], matchesB?: IMatch[]): number {\n    if ((!matchesA && !matchesB) || (!matchesA.length && !matchesB.length)) {\n        return 0 // make sure to not cause bad comparing when matches are not provided\n    }\n\n    if (!matchesB || !matchesB.length) {\n        return -1\n    }\n\n    if (!matchesA || !matchesA.length) {\n        return 1\n    }\n\n    // Compute match length of A (first to last match)\n    const matchStartA = matchesA[0].start\n    const matchEndA = matchesA[matchesA.length - 1].end\n    const matchLengthA = matchEndA - matchStartA\n\n    // Compute match length of B (first to last match)\n    const matchStartB = matchesB[0].start\n    const matchEndB = matchesB[matchesB.length - 1].end\n    const matchLengthB = matchEndB - matchStartB\n\n    // Prefer shorter match length\n    return matchLengthA === matchLengthB ? 0 : matchLengthB < matchLengthA ? 1 : -1\n}\n\nexport function fallbackCompare<T>(\n    itemA: T,\n    itemB: T,\n    query: IPreparedQuery,\n    accessor: IItemAccessor<T>,\n): number {\n    // check for label + description length and prefer shorter\n    const labelA = accessor.getItemLabel(itemA)\n    const labelB = accessor.getItemLabel(itemB)\n\n    const descriptionA = accessor.getItemDescription(itemA)\n    const descriptionB = accessor.getItemDescription(itemB)\n\n    const labelDescriptionALength = labelA.length + (descriptionA ? descriptionA.length : 0)\n    const labelDescriptionBLength = labelB.length + (descriptionB ? descriptionB.length : 0)\n\n    if (labelDescriptionALength !== labelDescriptionBLength) {\n        return labelDescriptionALength - labelDescriptionBLength\n    }\n\n    // check for path length and prefer shorter\n    const pathA = accessor.getItemPath(itemA)\n    const pathB = accessor.getItemPath(itemB)\n\n    if (pathA && pathB && pathA.length !== pathB.length) {\n        return pathA.length - pathB.length\n    }\n\n    // 7.) finally we have equal scores and equal length, we fallback to comparer\n\n    // compare by label\n    if (labelA !== labelB) {\n        return compareAnything(labelA, labelB, query.value)\n    }\n\n    // compare by description\n    if (descriptionA && descriptionB && descriptionA !== descriptionB) {\n        return compareAnything(descriptionA, descriptionB, query.value)\n    }\n\n    // compare by path\n    if (pathA && pathB && pathA !== pathB) {\n        return compareAnything(pathA, pathB, query.value)\n    }\n\n    // equal\n    return 0\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/Utilities.ts",
    "content": "/**\n * Assortment of imported Utility functions from VSCode\n */\n\nimport { CharCode } from \"./CharCode\"\n\nexport const isWindows = process.platform === \"win32\"\nexport const isMacintosh = process.platform === \"darwin\"\nexport const isLinux = process.platform === \"linux\"\n\n// The native path separator depending on the OS.\nexport const nativeSep = isWindows ? \"\\\\\" : \"/\"\n\nexport function isLower(code: number): boolean {\n    return CharCode.a <= code && code <= CharCode.z\n}\n\nexport function isUpper(code: number): boolean {\n    return CharCode.A <= code && code <= CharCode.Z\n}\n\nexport function isNumber(code: number): boolean {\n    return CharCode.Digit0 <= code && code <= CharCode.Digit9\n}\n\nexport function isWhitespace(code: number): boolean {\n    return (\n        code === CharCode.Space ||\n        code === CharCode.Tab ||\n        code === CharCode.LineFeed ||\n        code === CharCode.CarriageReturn\n    )\n}\n\nexport function isAlphanumeric(code: number): boolean {\n    return isLower(code) || isUpper(code) || isNumber(code)\n}\n\nexport function stripWildcards(pattern: string): string {\n    return pattern.replace(/\\*/g, \"\")\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/filters.ts",
    "content": "/* tslint:disable */\n/**\n * Imported functions from VSCode's filters.ts\n */\n\nimport { startsWithIgnoreCase } from \"./strings\"\nimport { isAlphanumeric, isLower, isNumber, isUpper, isWhitespace } from \"./Utilities\"\n\nexport interface IFilter {\n    // Returns null if word doesn't match.\n    (word: string, wordToMatchAgainst: string): IMatch[]\n}\n\nexport interface IMatch {\n    start: number\n    end: number\n}\n\nexport const matchesPrefix: IFilter = _matchesPrefix.bind(undefined, true)\n\nfunction _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: string): IMatch[] {\n    if (!wordToMatchAgainst || wordToMatchAgainst.length < word.length) {\n        return null\n    }\n\n    let matches: boolean\n    if (ignoreCase) {\n        matches = startsWithIgnoreCase(wordToMatchAgainst, word)\n    } else {\n        matches = wordToMatchAgainst.indexOf(word) === 0\n    }\n\n    if (!matches) {\n        return null\n    }\n\n    return word.length > 0 ? [{ start: 0, end: word.length }] : []\n}\n\nexport function createMatches(position: number[]): IMatch[] {\n    let ret: IMatch[] = []\n    if (!position) {\n        return ret\n    }\n    let last: IMatch\n    for (const pos of position) {\n        if (last && last.end === pos) {\n            last.end += 1\n        } else {\n            last = { start: pos, end: pos + 1 }\n            ret.push(last)\n        }\n    }\n    return ret\n}\n\nfunction nextAnchor(camelCaseWord: string, start: number): number {\n    for (let i = start; i < camelCaseWord.length; i++) {\n        let c = camelCaseWord.charCodeAt(i)\n        if (\n            isUpper(c) ||\n            isNumber(c) ||\n            (i > 0 && !isAlphanumeric(camelCaseWord.charCodeAt(i - 1)))\n        ) {\n            return i\n        }\n    }\n    return camelCaseWord.length\n}\n\nfunction _matchesCamelCase(word: string, camelCaseWord: string, i: number, j: number): IMatch[] {\n    if (i === word.length) {\n        return []\n    } else if (j === camelCaseWord.length) {\n        return null\n    } else if (word[i] !== camelCaseWord[j].toLowerCase()) {\n        return null\n    } else {\n        let result: IMatch[] = null\n        let nextUpperIndex = j + 1\n        result = _matchesCamelCase(word, camelCaseWord, i + 1, j + 1)\n        while (\n            !result &&\n            (nextUpperIndex = nextAnchor(camelCaseWord, nextUpperIndex)) < camelCaseWord.length\n        ) {\n            result = _matchesCamelCase(word, camelCaseWord, i + 1, nextUpperIndex)\n            nextUpperIndex++\n        }\n        return result === null ? null : join({ start: j, end: j + 1 }, result)\n    }\n}\n\ninterface ICamelCaseAnalysis {\n    upperPercent: number\n    lowerPercent: number\n    alphaPercent: number\n    numericPercent: number\n}\n\n// Heuristic to avoid computing camel case matcher for words that don't\n// look like camelCaseWords.\nfunction analyzeCamelCaseWord(word: string): ICamelCaseAnalysis {\n    let upper = 0,\n        lower = 0,\n        alpha = 0,\n        numeric = 0,\n        code = 0\n\n    for (let i = 0; i < word.length; i++) {\n        code = word.charCodeAt(i)\n\n        if (isUpper(code)) {\n            upper++\n        }\n        if (isLower(code)) {\n            lower++\n        }\n        if (isAlphanumeric(code)) {\n            alpha++\n        }\n        if (isNumber(code)) {\n            numeric++\n        }\n    }\n\n    let upperPercent = upper / word.length\n    let lowerPercent = lower / word.length\n    let alphaPercent = alpha / word.length\n    let numericPercent = numeric / word.length\n\n    return { upperPercent, lowerPercent, alphaPercent, numericPercent }\n}\n\nfunction isUpperCaseWord(analysis: ICamelCaseAnalysis): boolean {\n    const { upperPercent, lowerPercent } = analysis\n    return lowerPercent === 0 && upperPercent > 0.6\n}\n\nfunction isCamelCaseWord(analysis: ICamelCaseAnalysis): boolean {\n    const { upperPercent, lowerPercent, alphaPercent, numericPercent } = analysis\n    return lowerPercent > 0.2 && upperPercent < 0.8 && alphaPercent > 0.6 && numericPercent < 0.2\n}\n\n// Heuristic to avoid computing camel case matcher for words that don't\n// look like camel case patterns.\nfunction isCamelCasePattern(word: string): boolean {\n    let upper = 0,\n        lower = 0,\n        code = 0,\n        whitespace = 0\n\n    for (let i = 0; i < word.length; i++) {\n        code = word.charCodeAt(i)\n\n        if (isUpper(code)) {\n            upper++\n        }\n        if (isLower(code)) {\n            lower++\n        }\n        if (isWhitespace(code)) {\n            whitespace++\n        }\n    }\n\n    if ((upper === 0 || lower === 0) && whitespace === 0) {\n        return word.length <= 30\n    } else {\n        return upper <= 5\n    }\n}\n\nexport function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] {\n    if (!camelCaseWord) {\n        return null\n    }\n\n    camelCaseWord = camelCaseWord.trim()\n\n    if (camelCaseWord.length === 0) {\n        return null\n    }\n\n    if (!isCamelCasePattern(word)) {\n        return null\n    }\n\n    if (camelCaseWord.length > 60) {\n        return null\n    }\n\n    const analysis = analyzeCamelCaseWord(camelCaseWord)\n\n    if (!isCamelCaseWord(analysis)) {\n        if (!isUpperCaseWord(analysis)) {\n            return null\n        }\n\n        camelCaseWord = camelCaseWord.toLowerCase()\n    }\n\n    let result: IMatch[] = null\n    let i = 0\n\n    while (\n        i < camelCaseWord.length &&\n        (result = _matchesCamelCase(word.toLowerCase(), camelCaseWord, 0, i)) === null\n    ) {\n        i = nextAnchor(camelCaseWord, i + 1)\n    }\n\n    return result\n}\n\nfunction join(head: IMatch, tail: IMatch[]): IMatch[] {\n    if (tail.length === 0) {\n        tail = [head]\n    } else if (head.end === tail[0].start) {\n        tail[0].start = head.start\n    } else {\n        tail.unshift(head)\n    }\n    return tail\n}\n"
  },
  {
    "path": "browser/src/Services/Search/Scorer/strings.ts",
    "content": "/* tslint:disable */\n/**\n * Imported functions from VSCode's strings.ts\n */\n\nimport { CharCode } from \"./CharCode\"\n\nfunction isLowerAsciiLetter(code: number): boolean {\n    return code >= CharCode.a && code <= CharCode.z\n}\n\nfunction isUpperAsciiLetter(code: number): boolean {\n    return code >= CharCode.A && code <= CharCode.Z\n}\n\nfunction isAsciiLetter(code: number): boolean {\n    return isLowerAsciiLetter(code) || isUpperAsciiLetter(code)\n}\n\nexport function equalsIgnoreCase(a: string, b: string): boolean {\n    const len1 = a ? a.length : 0\n    const len2 = b ? b.length : 0\n\n    if (len1 !== len2) {\n        return false\n    }\n\n    return doEqualsIgnoreCase(a, b)\n}\n\nfunction doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean {\n    if (typeof a !== \"string\" || typeof b !== \"string\") {\n        return false\n    }\n\n    for (let i = 0; i < stopAt; i++) {\n        const codeA = a.charCodeAt(i)\n        const codeB = b.charCodeAt(i)\n\n        if (codeA === codeB) {\n            continue\n        }\n\n        // a-z A-Z\n        if (isAsciiLetter(codeA) && isAsciiLetter(codeB)) {\n            let diff = Math.abs(codeA - codeB)\n            if (diff !== 0 && diff !== 32) {\n                return false\n            }\n        } else {\n            // Any other charcode\n            if (\n                String.fromCharCode(codeA).toLowerCase() !==\n                String.fromCharCode(codeB).toLowerCase()\n            ) {\n                return false\n            }\n        }\n    }\n\n    return true\n}\n\nexport function startsWithIgnoreCase(str: string, candidate: string): boolean {\n    const candidateLength = candidate.length\n    if (candidate.length > str.length) {\n        return false\n    }\n\n    return doEqualsIgnoreCase(str, candidate, candidateLength)\n}\n"
  },
  {
    "path": "browser/src/Services/Search/SearchPaneView.tsx",
    "content": "/**\n * Search/index.tsx\n *\n * Entry point for search-related features\n */\n\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\nimport { IDisposable, IEvent } from \"oni-types\"\n\nimport { Workspace } from \"./../Workspace\"\n\nexport * from \"./SearchProvider\"\n\nimport styled from \"styled-components\"\nimport { SearchTextBox } from \"./SearchTextBox\"\n\nimport { SidebarEmptyPaneView } from \"./../../UI/components/SidebarEmptyPaneView\"\nimport { VimNavigator } from \"./../../UI/components/VimNavigator\"\n\nconst Label = styled.div`\n    margin: 8px;\n`\n\nexport interface ISearchPaneViewProps {\n    workspace: Workspace\n    onEnter: IEvent<void>\n    onLeave: IEvent<void>\n    onFocus: IEvent<void>\n    focusImmediately?: boolean\n\n    onSearchOptionsChanged: (opts: Oni.Search.Options) => void\n}\n\nexport interface ISearchPaneViewState {\n    activeWorkspace: string\n    isActive: boolean\n    activeTextbox: string\n\n    searchQuery: string\n    fileFilter: string\n}\n\nexport class SearchPaneView extends React.PureComponent<\n    ISearchPaneViewProps,\n    ISearchPaneViewState\n> {\n    private _subscriptions: IDisposable[] = []\n\n    constructor(props: ISearchPaneViewProps) {\n        super(props)\n\n        this.state = {\n            activeWorkspace: this.props.workspace.activeWorkspace,\n            isActive: false,\n            activeTextbox: null,\n            searchQuery: \"Search...\",\n            fileFilter: null,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._cleanExistingSubscriptions()\n\n        const s1 = this.props.onEnter.subscribe(() => this.setState({ isActive: true }))\n        const s2 = this.props.onLeave.subscribe(() => this.setState({ isActive: false }))\n        const s3 = this.props.workspace.onDirectoryChanged.subscribe((wd: string) =>\n            this.setState({ activeWorkspace: wd }),\n        )\n\n        const s4 = this.props.onFocus.subscribe(() =>\n            this.setState({ activeTextbox: \"textbox.query\" }),\n        )\n\n        this._subscriptions = [s1, s2, s3, s4]\n\n        if (this.props.focusImmediately) {\n            this.setState({\n                activeTextbox: \"textbox.query\",\n            })\n        }\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanExistingSubscriptions()\n    }\n\n    public render(): JSX.Element {\n        if (!this.state.activeWorkspace) {\n            return (\n                <SidebarEmptyPaneView\n                    active={this.state.isActive}\n                    contentsText=\"Nothing to search, yet!\"\n                    actionButtonText={\"Open Folder\"}\n                    onClickButton={() => this.props.workspace.openFolder()}\n                />\n            )\n        }\n\n        return (\n            <VimNavigator\n                active={this.state.isActive && !this.state.activeTextbox}\n                ids={[\"textbox.query\" /*, \"textbox.filter\"*/]}\n                onSelected={(selectedId: string) => {\n                    this._onSelected(selectedId)\n                }}\n                render={(selectedId: string) => {\n                    return (\n                        <div>\n                            <Label>Query</Label>\n                            <SearchTextBox\n                                val={this.state.searchQuery}\n                                onChangeText={val => this._onChangeSearchQuery(val)}\n                                onCommit={() => this._clearActiveTextbox()}\n                                onDismiss={() => this._clearActiveTextbox()}\n                                isFocused={selectedId === \"textbox.query\"}\n                                isActive={this.state.activeTextbox === \"textbox.query\"}\n                                onClick={() => this._onSelected(\"textbox.query\")}\n                            />\n                            {/*<Label>Filter</Label>\n                            <SearchTextBox\n                                val={this.state.fileFilter}\n                                onChangeText={val => this._onChangeFilesFilter(val)}\n                                onCommit={() => this._clearActiveTextbox()}\n                                onDismiss={() => this._clearActiveTextbox()}\n                                isFocused={selectedId === \"textbox.filter\"}\n                                isActive={this.state.activeTextbox === \"textbox.filter\"}\n                            />*/}\n                        </div>\n                    )\n                }}\n            />\n        )\n    }\n\n    private _cleanExistingSubscriptions(): void {\n        this._subscriptions.forEach(s => s.dispose())\n        this._subscriptions = []\n    }\n\n    // private _onChangeFilesFilter(val: string): void {\n    //     this.setState({\n    //         fileFilter: val,\n    //     })\n\n    //     this._startSearch()\n    // }\n\n    private _onChangeSearchQuery(val: string): void {\n        this.setState({\n            searchQuery: val,\n        })\n\n        this._startSearch(val)\n    }\n\n    // private _onCommit(): void {\n\n    // }\n\n    private _clearActiveTextbox(): void {\n        this.setState({ activeTextbox: null })\n    }\n\n    private _onSelected(selectedId: string): void {\n        if (selectedId === \"textbox.query\") {\n            this.setState({ activeTextbox: \"textbox.query\" })\n        } else if (selectedId === \"textbox.filter\") {\n            this.setState({ activeTextbox: \"textbox.filter\" })\n        }\n    }\n\n    private _startSearch(val: string): void {\n        this.props.onSearchOptionsChanged({\n            searchQuery: val,\n            fileFilter: this.state.fileFilter,\n            workspace: this.props.workspace.activeWorkspace,\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Search/SearchProvider.ts",
    "content": "import { Event, IEvent } from \"oni-types\"\n\nimport { configuration } from \"./../Configuration\"\n\nimport * as Oni from \"oni-api\"\n\nimport { FinderProcess } from \"./FinderProcess\"\nimport * as RipGrep from \"./RipGrep\"\n\nclass NullSearchQuery implements Oni.Search.Query {\n    public _onSearchResults = new Event<Oni.Search.Result>()\n\n    public start(): void {\n        return undefined\n    }\n\n    public cancel(): void {\n        return undefined\n    }\n\n    public get onSearchResults(): IEvent<Oni.Search.Result> {\n        return this._onSearchResults\n    }\n}\n\nexport class Search implements Oni.Search.ISearch {\n    public get nullSearch(): Oni.Search.Query {\n        return new NullSearchQuery()\n    }\n\n    public findInFile(opts: Oni.Search.Options): Oni.Search.Query {\n        const commandParts = [\n            RipGrep.getCommand(),\n            \"--ignore-case\",\n            ...RipGrep.getArguments(\n                configuration.getValue(\"oni.exclude\"),\n                configuration.getValue(\"editor.quickOpen.showHidden\"),\n            ),\n            // \"-e\",\n            ...(opts.fileFilter ? [\"-g\", opts.fileFilter] : []),\n            \"--\",\n            opts.searchQuery,\n            opts.workspace ? opts.workspace : \".\",\n        ]\n        return new SearchQuery(commandParts.join(\" \"), parseRipGrepLine)\n    }\n\n    public findInPath(opts: Oni.Search.Options): Oni.Search.Query {\n        const commandParts = [\n            RipGrep.getCommand(),\n            ...RipGrep.getArguments(\n                configuration.getValue(\"oni.exclude\"),\n                configuration.getValue(\"editor.quickOpen.showHidden\"),\n            ),\n            \"--files\",\n            \"--\",\n            opts.workspace ? opts.workspace : \".\",\n        ]\n        return new SearchQuery(commandParts.join(\" \"), parseRipGrepFilesLine)\n    }\n}\n\nfunction parseRipGrepLine(ripGrepResult: string): Oni.Search.ResultItem {\n    if (!ripGrepResult || ripGrepResult.length === 0) {\n        return null\n    }\n\n    const splitString = ripGrepResult.split(\":\")\n    if (splitString.length < 4) {\n        return null\n    }\n\n    const [fileName, line, column, ...result] = splitString\n    const text = result.join(\":\")\n\n    return {\n        fileName,\n        line: parseInt(line, 10),\n        column: parseInt(column, 10),\n        text,\n    }\n}\n\nfunction parseRipGrepFilesLine(line: string): Oni.Search.ResultItem {\n    if (!line || line.length === 0) {\n        return null\n    }\n\n    return {\n        fileName: line,\n        line: 0,\n        column: 0,\n        text: \"\",\n    }\n}\n\ntype IParseLine = (line: string) => Oni.Search.ResultItem\n\nclass SearchQuery implements Oni.Search.Query {\n    private _onSearchResults = new Event<Oni.Search.Result>()\n    private _finderProcess: FinderProcess\n\n    private _items: Oni.Search.ResultItem[] = []\n\n    public get onSearchResults(): IEvent<Oni.Search.Result> {\n        return this._onSearchResults\n    }\n\n    constructor(command: string, parseLine: IParseLine) {\n        this._finderProcess = new FinderProcess(command, \"\\n\")\n\n        this._finderProcess.onData.subscribe((lines: string[]) => {\n            const results = lines.map(parseLine).filter(item => item !== null)\n            this._items = [...this._items, ...results]\n            this._onSearchResults.dispatch({\n                items: this._items,\n                isComplete: false,\n            })\n        })\n\n        this._finderProcess.onComplete.subscribe(() => {\n            this._onSearchResults.dispatch({\n                items: this._items,\n                isComplete: true,\n            })\n        })\n    }\n\n    public start(): void {\n        this._items = []\n        this._finderProcess.start()\n    }\n\n    public cancel(): void {\n        this._finderProcess.stop()\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Search/SearchResultsSpinnerView.tsx",
    "content": "/**\n * Search/index.tsx\n *\n * Entry point for search-related features\n */\n\nimport * as React from \"react\"\n\nimport { IDisposable, IEvent } from \"oni-types\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport { withProps } from \"./../../UI/components/common\"\nimport { Icon, IconSize } from \"./../../UI/Icon\"\n\nexport interface ISearchResultSpinnerViewProps {\n    onSearchStarted: IEvent<void>\n    onSearchFinished: IEvent<void>\n}\n\nexport interface ISearchResultSpinnerViewState {\n    isActive: boolean\n}\n\nconst SpinnerWrapper = withProps<{ isActive: boolean }>(styled.div)`\n    opacity: ${props => (props.isActive ? \"0.5\" : \"0\")};\n    transition: opacity 0.5s ease-in;\n\n    width: 100%;\n    min-height: 5em;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    position: relative;\n`\n\nconst RotateKeyFrames = keyframes`\n    0% { transform: rotateZ(0deg); }\n    100% { transform: rotateZ(360deg); }\n`\n\nconst SpinnerRotator = styled.div`\n    animation: ${RotateKeyFrames} 0.5s linear infinite;\n    transform-origin: center;\n`\n\nexport class SearchResultSpinnerView extends React.PureComponent<\n    ISearchResultSpinnerViewProps,\n    ISearchResultSpinnerViewState\n> {\n    private _subscriptions: IDisposable[] = []\n\n    constructor(props: ISearchResultSpinnerViewProps) {\n        super(props)\n\n        this.state = {\n            isActive: false,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._cleanExistingSubscriptions()\n\n        const s1 = this.props.onSearchStarted.subscribe(() => this.setState({ isActive: true }))\n        const s2 = this.props.onSearchFinished.subscribe(() => this.setState({ isActive: false }))\n\n        this._subscriptions = [s1, s2]\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanExistingSubscriptions()\n    }\n\n    public render(): JSX.Element {\n        return (\n            <SpinnerWrapper isActive={this.state.isActive}>\n                <SpinnerRotator>\n                    <Icon name={\"circle-o-notch\"} size={IconSize.ThreeX} />\n                </SpinnerRotator>\n            </SpinnerWrapper>\n        )\n    }\n\n    private _cleanExistingSubscriptions(): void {\n        this._subscriptions.forEach(s => s.dispose())\n        this._subscriptions = []\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Search/SearchTextBox.tsx",
    "content": "/**\n * SearchTextBox.tsx\n *\n * Component for textbox in search\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\nimport { boxShadow, withProps } from \"./../../UI/components/common\"\nimport { TextInputView } from \"./../../UI/components/LightweightText\"\n\nexport interface ISearchTextBoxProps {\n    isActive: boolean\n    isFocused: boolean\n    val: string\n\n    onDismiss: () => void\n    onCommit: (newValue: string) => void\n    onChangeText: (newValue: string) => void\n    onClick: () => void\n}\n\nconst SearchBoxContainerWrapper = withProps<ISearchTextBoxProps>(styled.div)`\n    padding: 8px;\n\n    background-color: ${props => (props.isFocused ? \"rgba(0, 0, 0, 0.1)\" : \"transparent\")};\n    border-left: 2px solid ${props =>\n        props.isFocused ? props.theme[\"highlight.mode.normal.background\"] : \"transparent\"};\n`\n\nconst SearchTextBoxWrapper = withProps<ISearchTextBoxProps>(styled.div)`\n    padding: 8px;\n    border: ${props =>\n        props.isActive\n            ? \"2px solid \" + props.theme[\"highlight.mode.normal.background\"]\n            : \"1px solid \" + props.theme[\"editor.foreground\"]};\n    margin: 8px;\n    background-color: ${props => props.theme.background};\n\n    ${props => (props.isActive ? boxShadow : \"\")};\n\n    transition: all 0.1s ease-in;\n\n    input {\n        background-color: transparent;\n        color: ${props => props.theme[\"editor.foreground\"]}\n    }\n\n    cursor: text;\n`\n\nexport class SearchTextBox extends React.PureComponent<ISearchTextBoxProps, {}> {\n    public render(): JSX.Element {\n        const inner = this.props.isActive ? (\n            <TextInputView\n                defaultValue={this.props.val}\n                onCancel={this.props.onDismiss}\n                onChange={elem => this.props.onChangeText(elem.currentTarget.value)}\n                onComplete={this.props.onCommit}\n            />\n        ) : (\n            <div>{this.props.val}</div>\n        )\n        return (\n            <SearchBoxContainerWrapper {...this.props} onClick={this.props.onClick}>\n                <SearchTextBoxWrapper {...this.props}>{inner}</SearchTextBoxWrapper>\n            </SearchBoxContainerWrapper>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Search/index.tsx",
    "content": "import * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { Workspace } from \"./../Workspace\"\n\nimport * as React from \"react\"\n\nimport { Subject } from \"rxjs/Subject\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { SearchPaneView } from \"./SearchPaneView\"\nimport { SearchResultSpinnerView } from \"./SearchResultsSpinnerView\"\n\nimport { getInstance as getSidebarManager } from \"../Sidebar\" // TODO: Replace with oni-api usage\n\nexport class SearchPane {\n    private _onEnter = new Event<void>()\n    private _onLeave = new Event<void>()\n    private _onSearchStarted = new Event<void>()\n    private _onSearchCompleted = new Event<void>()\n    private _shouldFocusAutomatically: boolean = false\n\n    private _currentQuery: Oni.Search.Query\n\n    private _searchOptionsObservable = new Subject<Oni.Search.Options>()\n\n    public get id(): string {\n        return \"oni.sidebar.search\"\n    }\n\n    public get title(): string {\n        return \"Search\"\n    }\n\n    constructor(private _onFocusEvent: IEvent<void>, private _oni: Oni.Plugin.Api) {\n        this._searchOptionsObservable.auditTime(100).subscribe((opts: Oni.Search.Options) => {\n            this._startNewSearch(opts)\n        })\n\n        this._onFocusEvent.subscribe(() => {\n            this._shouldFocusAutomatically = true\n        })\n    }\n\n    public enter(): void {\n        this._onEnter.dispatch()\n    }\n\n    public leave(): void {\n        this._onLeave.dispatch()\n    }\n\n    public render(): JSX.Element {\n        const immedateFocus = this._shouldFocusAutomatically\n        this._shouldFocusAutomatically = false\n\n        const typelessWorkspace: any = this._oni.workspace // TODO: Work-around this hack\n        const workspace: Workspace = typelessWorkspace // TODO: Work-around this hack\n\n        return (\n            <div>\n                <SearchPaneView\n                    workspace={workspace}\n                    onEnter={this._onEnter}\n                    onLeave={this._onLeave}\n                    onFocus={this._onFocusEvent}\n                    onSearchOptionsChanged={opts => this._onSearchOptionsChanged(opts)}\n                    focusImmediately={immedateFocus}\n                />\n                <SearchResultSpinnerView\n                    onSearchStarted={this._onSearchStarted}\n                    onSearchFinished={this._onSearchCompleted}\n                />\n            </div>\n        )\n    }\n\n    private _onSearchOptionsChanged(searchOpts: Oni.Search.Options): void {\n        this._searchOptionsObservable.next(searchOpts)\n    }\n\n    private _startNewSearch(searchOpts: Oni.Search.Options): void {\n        if (this._currentQuery) {\n            this._currentQuery.cancel()\n        }\n\n        if (!searchOpts.searchQuery || searchOpts.searchQuery.length < 1) {\n            return\n        }\n\n        Log.verbose(\"[SearchPane::_startNewSearch]: \" + searchOpts.searchQuery)\n\n        this._onSearchStarted.dispatch()\n\n        const query = (this._currentQuery = this._oni.search.findInFile(searchOpts))\n        const toQuickFixItem = (r: Oni.Search.ResultItem) => {\n            return {\n                filename: r.fileName,\n                lnum: r.line,\n                col: r.column,\n                text: r.text.trim(),\n            }\n        }\n        query.onSearchResults.subscribe(result => {\n            if (result.isComplete) {\n                this._onSearchCompleted.dispatch()\n                this._oni.populateQuickFix(result.items.map(toQuickFixItem))\n            }\n        })\n        query.start()\n    }\n}\n\nexport function activate(oni: any): any {\n    const onFocusEvent = new Event<void>()\n\n    const oniApi: Oni.Plugin.Api = oni\n\n    // TODO: Add sidebar.add to the API and use oniApi instead of oni\n    oni.sidebar.add(\"search\", new SearchPane(onFocusEvent, oni))\n\n    const sidebarManager = getSidebarManager() // TODO: Remove\n\n    const searchAllFiles = () => {\n        sidebarManager.toggleVisibilityById(\"oni.sidebar.search\") // TODO: Use oni-api instead\n        // TODO: Add sidebar.setActiveEntry to the API and use oni as Oni (API)\n        // oni.sidebar.setActiveEntry(\"oni.sidebar.search\")\n        onFocusEvent.dispatch()\n    }\n\n    oniApi.commands.registerCommand({\n        command: \"search.searchAllFiles\",\n        name: \"Search: All files\",\n        detail: \"Search across files in the active workspace\",\n        execute: searchAllFiles,\n        enabled: () => !!oniApi.workspace.activeWorkspace,\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Sessions/SessionManager.ts",
    "content": "import * as fs from \"fs-extra\"\nimport { Editor, EditorManager, Plugin } from \"oni-api\"\nimport { IEvent } from \"oni-types\"\nimport * as path from \"path\"\n\nimport { SidebarManager } from \"../Sidebar\"\nimport { SessionActions, SessionsPane, store } from \"./\"\nimport { getPersistentStore, IPersistentStore } from \"./../../PersistentStore\"\nimport { getUserConfigFolderPath } from \"./../../Services/Configuration/UserConfiguration\"\n\nexport interface ISession {\n    name: string\n    id: string\n    file: string\n    directory: string\n    updatedAt?: string\n    workspace: string\n    // can be use to save other metadata for restoration like statusbar info or sidebar info etc\n    metadata?: { [key: string]: any }\n}\n\nexport interface ISessionService {\n    sessionsDir: string\n    allSessions: ISession[]\n    persistSession(sessionName: string): Promise<ISession>\n    restoreSession(sessionName: string): Promise<ISession>\n}\n\nexport interface UpdatedOni extends Plugin.Api {\n    editors: UpdatedEditorManager\n}\n\ninterface UpdatedEditorManager extends EditorManager {\n    activeEditor: UpdatedEditor\n}\n\ninterface UpdatedEditor extends Editor {\n    onQuit: IEvent<void>\n    persistSession(sessionDetails: ISession): Promise<ISession>\n    restoreSession(sessionDetails: ISession): Promise<ISession>\n    getCurrentSession(): Promise<string | void>\n}\n\n/**\n * Class SessionManager\n *\n * Provides a service to manage oni session i.e. buffers, screen layout etc.\n *\n */\nexport class SessionManager implements ISessionService {\n    private _store = store({ sessionManager: this, fs })\n    private get _sessionsDir() {\n        const defaultDirectory = path.join(getUserConfigFolderPath(), \"sessions\")\n        const userDirectory = this._oni.configuration.getValue<string>(\n            \"experimental.sessions.directory\",\n        )\n        const directory = userDirectory || defaultDirectory\n        return directory\n    }\n\n    constructor(\n        private _oni: UpdatedOni,\n        private _sidebarManager: SidebarManager,\n        private _persistentStore: IPersistentStore<{ [sessionName: string]: ISession }>,\n    ) {\n        fs.ensureDirSync(this.sessionsDir)\n        const enabled = this._oni.configuration.getValue<boolean>(\"experimental.sessions.enabled\")\n        if (enabled) {\n            this._store.dispatch({ type: \"POPULATE_SESSIONS\" })\n            this._sidebarManager.add(\n                \"save\",\n                new SessionsPane({ store: this._store, commands: this._oni.commands }),\n            )\n        }\n        this._setupSubscriptions()\n    }\n\n    public get allSessions() {\n        const state = this._store.getState()\n        return state.sessions\n    }\n\n    public get sessionsDir() {\n        return this._sessionsDir\n    }\n\n    public async updateOniSession(name: string, value: Partial<ISession>) {\n        const persistedSessions = await this._persistentStore.get()\n        if (name in persistedSessions) {\n            this._persistentStore.set({\n                ...persistedSessions,\n                [name]: { ...persistedSessions[name], ...value },\n            })\n        }\n    }\n\n    public async createOniSession(sessionName: string) {\n        const persistedSessions = await this._persistentStore.get()\n        const file = this._getSessionFilename(sessionName)\n\n        const session: ISession = {\n            file,\n            id: sessionName,\n            name: sessionName,\n            directory: this.sessionsDir,\n            workspace: this._oni.workspace.activeWorkspace,\n            metadata: null,\n        }\n\n        this._persistentStore.set({ ...persistedSessions, [sessionName]: session })\n\n        return session\n    }\n\n    /**\n     * Retrieve or Create a persistent Oni Session\n     *\n     * @name getSessionFromStore\n     * @function\n     * @param {string} sessionName The name of the session\n     * @returns {ISession} The session metadata object\n     */\n    public async getSessionFromStore(name: string) {\n        const sessions = await this._persistentStore.get()\n        if (name in sessions) {\n            return sessions[name]\n        }\n        return this.createOniSession(name)\n    }\n\n    public persistSession = async (sessionName: string) => {\n        const sessionDetails = await this.getSessionFromStore(sessionName)\n        await this._oni.editors.activeEditor.persistSession(sessionDetails)\n        return sessionDetails\n    }\n\n    public deleteSession = async (sessionName: string) => {\n        await this._persistentStore.delete(sessionName)\n    }\n\n    public getCurrentSession = async () => {\n        const filepath = await this._oni.editors.activeEditor.getCurrentSession()\n        if (!filepath) {\n            return null\n        }\n        const [name] = path.basename(filepath).split(\".\")\n        return filepath.includes(this._sessionsDir) ? this.getSessionFromStore(name) : null\n    }\n\n    public restoreSession = async (name: string) => {\n        const sessionDetails = await this.getSessionFromStore(name)\n        await this._oni.editors.activeEditor.restoreSession(sessionDetails)\n        const session = await this.getCurrentSession()\n        return session\n    }\n\n    private _getSessionFilename(name: string) {\n        return path.join(this.sessionsDir, `${name}.vim`)\n    }\n\n    private _setupSubscriptions() {\n        this._oni.editors.activeEditor.onBufferEnter.subscribe(() => {\n            this._store.dispatch(SessionActions.updateCurrentSession())\n        })\n        this._oni.editors.activeEditor.onQuit.subscribe(() => {\n            this._store.dispatch(SessionActions.updateCurrentSession())\n        })\n    }\n}\n\nfunction init() {\n    let instance: SessionManager\n    return {\n        getInstance: () => instance,\n        activate: (oni: Plugin.Api, sidebarManager: SidebarManager) => {\n            const persistentStore = getPersistentStore(\"sessions\", {}, 1)\n            instance = new SessionManager(oni as UpdatedOni, sidebarManager, persistentStore)\n        },\n    }\n}\nexport const { activate, getInstance } = init()\n"
  },
  {
    "path": "browser/src/Services/Sessions/Sessions.tsx",
    "content": "import * as path from \"path\"\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport SectionTitle from \"../../UI/components/SectionTitle\"\nimport { Icon } from \"../../UI/Icon\"\n\nimport styled, { css, sidebarItemSelected, withProps } from \"../../UI/components/common\"\nimport TextInputView from \"../../UI/components/LightweightText\"\nimport { VimNavigator } from \"../../UI/components/VimNavigator\"\nimport { getTimeSince } from \"../../Utility\"\nimport { ISession, ISessionState, SessionActions } from \"./\"\n\ninterface IStateProps {\n    sessions: ISession[]\n    active: boolean\n    creating: boolean\n    selected: ISession\n}\n\ninterface ISessionActions {\n    populateSessions: () => void\n    updateSelection: (selected: string) => void\n    getAllSessions: (sessions: ISession[]) => void\n    updateSession: (session: ISession) => void\n    restoreSession: (session: string) => void\n    persistSession: (session: string) => void\n    createSession: () => void\n    cancelCreating: () => void\n}\n\ninterface IConnectedProps extends IStateProps, ISessionActions {}\n\ninterface ISessionItem {\n    session: ISession\n    isSelected: boolean\n    onClick: () => void\n}\n\nexport const Container = styled.div`\n    padding: 0 1em;\n`\n\nconst SessionItem: React.SFC<ISessionItem> = ({ session, isSelected, onClick }) => {\n    const truncatedWorkspace = session.workspace\n        .split(path.sep)\n        .slice(-2)\n        .join(path.sep)\n\n    return (\n        <ListItem isSelected={isSelected} onClick={onClick}>\n            <div>\n                <strong>\n                    <Icon name=\"file\" /> Name: {session.name}\n                </strong>\n            </div>\n            <div>Workspace: {truncatedWorkspace}</div>\n            {<div>Last updated: {getTimeSince(new Date(session.updatedAt))} ago</div>}\n        </ListItem>\n    )\n}\n\nconst inputStyles = css`\n    background-color: transparent;\n    width: 100%;\n    font-family: inherit;\n    font-size: inherit;\n    color: ${p => p.theme[\"sidebar.foreground\"]};\n`\n\nconst ListItem = withProps<Partial<ISessionItem>>(styled.li)`\n    box-sizing: border-box;\n    padding: 0.5em 1em;\n    ${sidebarItemSelected};\n`\n\nconst List = styled.ul`\n    list-style-type: none;\n    padding: 0;\n    margin: 0;\n`\n\ninterface IState {\n    sessionName: string\n    showAll: boolean\n}\n\ninterface IIDs {\n    input: string\n    title: string\n}\n\nexport class Sessions extends React.PureComponent<IConnectedProps, IState> {\n    public readonly _ID: Readonly<IIDs> = {\n        input: \"new_session\",\n        title: \"title\",\n    }\n\n    public state = {\n        sessionName: \"\",\n        showAll: true,\n    }\n\n    public async componentDidMount() {\n        this.props.populateSessions()\n    }\n\n    public updateSelection = (selected: string) => {\n        this.props.updateSelection(selected)\n    }\n\n    public handleSelection = async (id: string) => {\n        const { sessionName } = this.state\n        const inputSelected = id === this._ID.input\n        const isTitle = id === this._ID.title\n        const isReadonlyField = id in this._ID\n        switch (true) {\n            case inputSelected && this.props.creating:\n                await this.props.persistSession(sessionName)\n                break\n            case inputSelected && !this.props.creating:\n                this.props.createSession()\n                break\n            case isTitle:\n                this.setState({ showAll: !this.state.showAll })\n                break\n            case isReadonlyField:\n                break\n            default:\n                await this.props.restoreSession(id)\n                break\n        }\n    }\n\n    public restoreSession = async (selected: string) => {\n        if (selected) {\n            await this.props.restoreSession(selected)\n        }\n    }\n\n    public handleChange: React.ChangeEventHandler<HTMLInputElement> = evt => {\n        const { value } = evt.currentTarget\n        this.setState({ sessionName: value })\n    }\n\n    public persistSession = async () => {\n        const { sessionName } = this.state\n        if (sessionName) {\n            await this.props.persistSession(sessionName)\n        }\n    }\n\n    public handleCancel = () => {\n        if (this.props.creating) {\n            this.props.cancelCreating()\n        }\n        this.setState({ sessionName: \"\" })\n    }\n\n    public render() {\n        const { showAll } = this.state\n        const { sessions, active, creating } = this.props\n        const ids = [this._ID.title, this._ID.input, ...sessions.map(({ id }) => id)]\n        return (\n            <VimNavigator\n                ids={ids}\n                active={active}\n                onSelected={this.handleSelection}\n                onSelectionChanged={this.updateSelection}\n                render={(selectedId, updateSelection) => (\n                    <List>\n                        <SectionTitle\n                            active\n                            count={sessions.length}\n                            title=\"All Sessions\"\n                            testId=\"sessions-title\"\n                            isSelected={selectedId === this._ID.title}\n                            onClick={() => this.handleSelection(selectedId)}\n                        />\n                        {showAll && (\n                            <>\n                                <ListItem isSelected={selectedId === this._ID.input}>\n                                    {creating ? (\n                                        <TextInputView\n                                            styles={inputStyles}\n                                            onChange={this.handleChange}\n                                            onCancel={this.handleCancel}\n                                            onComplete={this.persistSession}\n                                            defaultValue=\"Enter a new Session Name\"\n                                        />\n                                    ) : (\n                                        <div onClick={() => this.handleSelection(selectedId)}>\n                                            <Icon name=\"pencil\" /> Create a new session\n                                        </div>\n                                    )}\n                                </ListItem>\n                                {sessions.length ? (\n                                    sessions.map((session, idx) => (\n                                        <SessionItem\n                                            key={session.id}\n                                            session={session}\n                                            isSelected={selectedId === session.id}\n                                            onClick={() => {\n                                                updateSelection(session.id)\n                                                this.handleSelection(session.id)\n                                            }}\n                                        />\n                                    ))\n                                ) : (\n                                    <Container>No Sessions Saved</Container>\n                                )}\n                            </>\n                        )}\n                    </List>\n                )}\n            />\n        )\n    }\n}\n\nconst mapStateToProps = ({ sessions, selected, active, creating }: ISessionState): IStateProps => ({\n    sessions,\n    active,\n    creating,\n    selected,\n})\n\nexport default connect<IStateProps, ISessionActions>(mapStateToProps, SessionActions)(Sessions)\n"
  },
  {
    "path": "browser/src/Services/Sessions/SessionsPane.tsx",
    "content": "import { Commands } from \"oni-api\"\nimport * as React from \"react\"\nimport { Provider } from \"react-redux\"\n\nimport { ISessionStore, Sessions } from \"./\"\n\ninterface SessionPaneProps {\n    commands: Commands.Api\n    store: ISessionStore\n}\n\n/**\n * Class SessionsPane\n *\n * A Side bar pane for Oni's Session Management\n *\n */\nexport default class SessionsPane {\n    private _store: ISessionStore\n    private _commands: Commands.Api\n\n    constructor({ store, commands }: SessionPaneProps) {\n        this._commands = commands\n        this._store = store\n\n        this._setupCommands()\n    }\n\n    get id() {\n        return \"oni.sidebar.sessions\"\n    }\n\n    public get title() {\n        return \"Sessions\"\n    }\n\n    public enter() {\n        this._store.dispatch({ type: \"ENTER\" })\n    }\n\n    public leave() {\n        this._store.dispatch({ type: \"LEAVE\" })\n    }\n\n    public render() {\n        return (\n            <Provider store={this._store}>\n                <Sessions />\n            </Provider>\n        )\n    }\n\n    private _isActive = () => {\n        const state = this._store.getState()\n        return state.active && !state.creating\n    }\n\n    private _deleteSession = () => {\n        this._store.dispatch({ type: \"DELETE_SESSION\" })\n    }\n\n    private _setupCommands() {\n        this._commands.registerCommand({\n            command: \"oni.sessions.delete\",\n            name: \"Sessions: Delete the current session\",\n            detail: \"Delete the current or selected session\",\n            enabled: this._isActive,\n            execute: this._deleteSession,\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Sessions/SessionsStore.ts",
    "content": "import \"rxjs\"\n\nimport * as fsExtra from \"fs-extra\"\nimport * as path from \"path\"\nimport { Store } from \"redux\"\nimport { combineEpics, createEpicMiddleware, Epic, ofType } from \"redux-observable\"\nimport { from } from \"rxjs/observable/from\"\nimport { auditTime, catchError, filter, flatMap } from \"rxjs/operators\"\n\nimport { ISession, SessionManager } from \"./\"\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nexport interface ISessionState {\n    sessions: ISession[]\n    selected: ISession\n    currentSession: ISession\n    active: boolean\n    creating: boolean\n}\n\nconst DefaultState: ISessionState = {\n    sessions: [],\n    selected: null,\n    active: false,\n    creating: false,\n    currentSession: null,\n}\n\ninterface IGenericAction<N, T = undefined> {\n    type: N\n    payload?: T\n}\n\nexport type ISessionStore = Store<ISessionState>\n\nexport type IUpdateMultipleSessions = IGenericAction<\"GET_ALL_SESSIONS\", { sessions: ISession[] }>\nexport type IUpdateSelection = IGenericAction<\"UPDATE_SELECTION\", { selected: string }>\nexport type IUpdateSession = IGenericAction<\"UPDATE_SESSION\", { session: ISession }>\nexport type IRestoreSession = IGenericAction<\"RESTORE_SESSION\", { sessionName: string }>\nexport type IPersistSession = IGenericAction<\"PERSIST_SESSION\", { sessionName: string }>\nexport type IPersistSessionSuccess = IGenericAction<\"PERSIST_SESSION_SUCCESS\">\nexport type IPersistSessionFailed = IGenericAction<\"PERSIST_SESSION_FAILED\", { error: Error }>\nexport type IRestoreSessionError = IGenericAction<\"RESTORE_SESSION_ERROR\", { error: Error }>\nexport type IDeleteSession = IGenericAction<\"DELETE_SESSION\">\nexport type IDeleteSessionSuccess = IGenericAction<\"DELETE_SESSION_SUCCESS\">\nexport type IDeleteSessionFailed = IGenericAction<\"DELETE_SESSION_FAILED\">\nexport type IUpdateCurrentSession = IGenericAction<\"UPDATE_CURRENT_SESSION\">\nexport type ISetCurrentSession = IGenericAction<\"SET_CURRENT_SESSION\", { session: ISession }>\nexport type IPopulateSessions = IGenericAction<\"POPULATE_SESSIONS\">\nexport type ICreateSession = IGenericAction<\"CREATE_SESSION\">\nexport type ICancelCreateSession = IGenericAction<\"CANCEL_NEW_SESSION\">\nexport type IEnter = IGenericAction<\"ENTER\">\nexport type ILeave = IGenericAction<\"LEAVE\">\n\nexport type ISessionActions =\n    | IUpdateMultipleSessions\n    | ICancelCreateSession\n    | IRestoreSessionError\n    | IUpdateCurrentSession\n    | IPopulateSessions\n    | IUpdateSelection\n    | IUpdateSession\n    | IPersistSession\n    | IPersistSessionSuccess\n    | IPersistSessionFailed\n    | IDeleteSession\n    | IDeleteSessionSuccess\n    | IDeleteSessionFailed\n    | IRestoreSession\n    | ISetCurrentSession\n    | ICreateSession\n    | IEnter\n    | ILeave\n\nexport const SessionActions = {\n    persistSessionSuccess: () => ({ type: \"PERSIST_SESSION_SUCCESS\" } as IPersistSessionSuccess),\n    populateSessions: () => ({ type: \"POPULATE_SESSIONS\" } as IPopulateSessions),\n    deleteSession: () => ({ type: \"DELETE_SESSION\" } as IDeleteSession),\n    cancelCreating: () => ({ type: \"CANCEL_NEW_SESSION\" } as ICancelCreateSession),\n    createSession: () => ({ type: \"CREATE_SESSION\" } as ICreateSession),\n    updateCurrentSession: () => ({ type: \"UPDATE_CURRENT_SESSION\" } as IUpdateCurrentSession),\n    deleteSessionSuccess: () => ({ type: \"DELETE_SESSION_SUCCESS\" } as IDeleteSessionSuccess),\n\n    updateSession: (session: ISession) => ({ type: \"UPDATE_SESSION\", session } as IUpdateSession),\n    setCurrentSession: (session: ISession) =>\n        ({ type: \"SET_CURRENT_SESSION\", payload: { session } } as ISetCurrentSession),\n\n    deleteSessionFailed: (error: Error) =>\n        ({ type: \"DELETE_SESSION_FAILED\", error } as IDeleteSessionFailed),\n\n    persistSessionFailed: (error: Error) =>\n        ({ type: \"PERSIST_SESSION_FAILED\", error } as IPersistSessionFailed),\n\n    updateSelection: (selected: string) =>\n        ({ type: \"UPDATE_SELECTION\", payload: { selected } } as IUpdateSelection),\n\n    getAllSessions: (sessions: ISession[]) =>\n        ({\n            type: \"GET_ALL_SESSIONS\",\n            payload: { sessions },\n        } as IUpdateMultipleSessions),\n\n    persistSession: (sessionName: string) =>\n        ({\n            type: \"PERSIST_SESSION\",\n            payload: { sessionName },\n        } as IPersistSession),\n\n    restoreSessionError: (error: Error) =>\n        ({\n            type: \"RESTORE_SESSION_ERROR\",\n            payload: { error },\n        } as IRestoreSessionError),\n\n    restoreSession: (sessionName: string) =>\n        ({\n            type: \"RESTORE_SESSION\",\n            payload: { sessionName },\n        } as IRestoreSession),\n}\n\ntype SessionEpic = Epic<ISessionActions, ISessionState, Dependencies>\n\nexport const persistSessionEpic: SessionEpic = (action$, store, { sessionManager }) =>\n    action$.pipe(\n        ofType(\"PERSIST_SESSION\"),\n        auditTime(200),\n        flatMap((action: IPersistSession) => {\n            return from(sessionManager.persistSession(action.payload.sessionName)).pipe(\n                flatMap(session => {\n                    return [\n                        SessionActions.cancelCreating(),\n                        SessionActions.persistSessionSuccess(),\n                        SessionActions.setCurrentSession(session),\n                        SessionActions.populateSessions(),\n                    ]\n                }),\n                catchError(error => [SessionActions.persistSessionFailed(error)]),\n            )\n        }),\n    )\n\nconst updateCurrentSessionEpic: SessionEpic = (action$, store, { fs, sessionManager }) => {\n    return action$.pipe(\n        ofType(\"UPDATE_CURRENT_SESSION\"),\n        auditTime(200),\n        flatMap(() =>\n            from(sessionManager.getCurrentSession()).pipe(\n                filter(session => !!session),\n                flatMap(currentSession => [SessionActions.persistSession(currentSession.name)]),\n                catchError(error => [SessionActions.persistSessionFailed(error)]),\n            ),\n        ),\n    )\n}\n\nconst deleteSessionEpic: SessionEpic = (action$, store, { fs, sessionManager }) =>\n    action$.pipe(\n        ofType(\"DELETE_SESSION\"),\n        flatMap(() => {\n            const { selected, currentSession } = store.getState()\n            const sessionToDelete = selected || currentSession\n            return from(\n                fs\n                    .remove(sessionToDelete.file)\n                    .then(() => sessionManager.deleteSession(sessionToDelete.name)),\n            ).pipe(\n                flatMap(() => [\n                    SessionActions.deleteSessionSuccess(),\n                    SessionActions.populateSessions(),\n                ]),\n                catchError(error => {\n                    return [SessionActions.deleteSessionFailed(error)]\n                }),\n            )\n        }),\n    )\n\nconst restoreSessionEpic: SessionEpic = (action$, store, { sessionManager }) =>\n    action$.pipe(\n        ofType(\"RESTORE_SESSION\"),\n        flatMap((action: IRestoreSession) =>\n            from(sessionManager.restoreSession(action.payload.sessionName)).pipe(\n                flatMap(session => [\n                    SessionActions.setCurrentSession(session),\n                    SessionActions.populateSessions(),\n                ]),\n            ),\n        ),\n        catchError(error => [SessionActions.restoreSessionError(error)]),\n    )\n\nexport const fetchSessionsEpic: SessionEpic = (action$, store, { fs, sessionManager }) =>\n    action$.pipe(\n        ofType(\"POPULATE_SESSIONS\"),\n        flatMap((action: IPopulateSessions) => {\n            return from(\n                fs.readdir(sessionManager.sessionsDir).then(async dir => {\n                    const metadata = await Promise.all(\n                        dir.map(async file => {\n                            const filepath = path.join(sessionManager.sessionsDir, file)\n                            // use fs.stat mtime to figure when last a file was modified\n                            const { mtime } = await fs.stat(filepath)\n                            const [name] = file.split(\".\")\n                            return {\n                                name,\n                                file: filepath,\n                                updatedAt: mtime.toUTCString(),\n                            }\n                        }),\n                    )\n\n                    const sessions = Promise.all(\n                        metadata.map(async ({ file, name, updatedAt }) => {\n                            const savedSession = await sessionManager.getSessionFromStore(name)\n                            await sessionManager.updateOniSession(name, { updatedAt })\n                            return { ...savedSession, updatedAt }\n                        }),\n                    )\n                    return sessions\n                }),\n            ).flatMap(sessions => [SessionActions.getAllSessions(sessions)])\n        }),\n    )\n\nconst findSelectedSession = (sessions: ISession[], selected: string) =>\n    sessions.find(session => session.id === selected)\n\nconst updateSessions = (sessions: ISession[], newSession: ISession) =>\n    sessions.map(session => (session.id === newSession.id ? newSession : session))\n\nfunction reducer(state: ISessionState, action: ISessionActions) {\n    switch (action.type) {\n        case \"UPDATE_SESSION\":\n            return {\n                ...state,\n                sessions: updateSessions(state.sessions, action.payload.session),\n            }\n        case \"GET_ALL_SESSIONS\":\n            return {\n                ...state,\n                sessions: action.payload.sessions,\n            }\n        case \"CREATE_SESSION\":\n            return {\n                ...state,\n                creating: true,\n            }\n        case \"DELETE_SESSION_SUCCESS\":\n            return {\n                ...state,\n                currentSession: null,\n            }\n        case \"SET_CURRENT_SESSION\":\n            return {\n                ...state,\n                currentSession: action.payload.session,\n            }\n        case \"CANCEL_NEW_SESSION\":\n            return {\n                ...state,\n                creating: false,\n            }\n        case \"ENTER\":\n            return {\n                ...state,\n                active: true,\n            }\n        case \"LEAVE\":\n            return {\n                ...state,\n                active: false,\n            }\n        case \"UPDATE_SELECTION\":\n            return {\n                ...state,\n                selected: findSelectedSession(state.sessions, action.payload.selected),\n            }\n        default:\n            return state\n    }\n}\n\ninterface Dependencies {\n    fs: typeof fsExtra\n    sessionManager: SessionManager\n}\n\nconst createStore = (dependencies: Dependencies) =>\n    createReduxStore(\"sessions\", reducer, DefaultState, [\n        createEpicMiddleware<ISessionActions, ISessionState, Dependencies>(\n            combineEpics(\n                fetchSessionsEpic,\n                persistSessionEpic,\n                restoreSessionEpic,\n                updateCurrentSessionEpic,\n                deleteSessionEpic,\n            ),\n            { dependencies },\n        ),\n    ])\n\nexport default createStore\n"
  },
  {
    "path": "browser/src/Services/Sessions/index.ts",
    "content": "export * from \"./SessionManager\"\nexport * from \"./SessionsStore\"\nexport { default as SessionsPane } from \"./SessionsPane\"\nexport { default as Sessions } from \"./Sessions\"\nexport { default as store } from \"./SessionsStore\"\n"
  },
  {
    "path": "browser/src/Services/Sidebar/SidebarContentSplit.tsx",
    "content": "/**\n * SidebarContentSplit.tsx\n */\n\nimport * as React from \"react\"\nimport { connect, Provider } from \"react-redux\"\nimport styled, { keyframes } from \"styled-components\"\n\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { enableMouse, withProps } from \"./../../UI/components/common\"\n\nimport { ISidebarEntry, ISidebarState, SidebarManager, SidebarPane } from \"./SidebarStore\"\n\nexport const getActiveEntry = (state: ISidebarState): ISidebarEntry => {\n    const filteredEntries = state.entries.filter(entry => entry.id === state.activeEntryId)\n\n    const activeEntry = filteredEntries.length > 0 ? filteredEntries[0] : null\n\n    return activeEntry\n}\n\n/**\n * Split that is the container for the active sidebar item\n */\nexport class SidebarContentSplit {\n    private _onEnterEvent = new Event<void>()\n    private _onLeaveEvent = new Event<void>()\n\n    public get activePane(): SidebarPane {\n        const entry = getActiveEntry(this._sidebarManager.store.getState())\n\n        return entry && entry.pane ? entry.pane : null\n    }\n\n    constructor(private _sidebarManager: SidebarManager) {}\n\n    public enter(): void {\n        const pane: any = this.activePane\n        if (pane && pane.enter) {\n            pane.enter()\n        }\n\n        this._onEnterEvent.dispatch()\n    }\n\n    public leave(): void {\n        const pane: any = this.activePane\n        if (pane && pane.leave) {\n            pane.leave()\n        }\n\n        this._onLeaveEvent.dispatch()\n    }\n\n    public render(): JSX.Element {\n        return (\n            <Provider store={this._sidebarManager.store}>\n                <SidebarContent onEnter={this._onEnterEvent} onLeave={this._onLeaveEvent} />\n            </Provider>\n        )\n    }\n}\n\nexport interface ISidebarContentViewProps extends ISidebarContentContainerProps {\n    activeEntry: ISidebarEntry\n    width: string\n}\n\nexport interface ISidebarContentContainerProps {\n    onEnter: IEvent<void>\n    onLeave: IEvent<void>\n}\n\nexport interface ISidebarContentViewState {\n    active: boolean\n}\n\nconst EntranceKeyframes = keyframes`\n    0% { opacity: 0.5; transform: translateX(-5px); }\n    100%% { opacity: 1; transform: translateX(0px); }\n`\n\nexport const SidebarContentWrapper = withProps<{}>(styled.div)`\n    ${enableMouse}\n    width: ${props => props.width};\n    color: ${props => props.theme[\"editor.foreground\"]};\n    background-color: ${props => props.theme[\"editor.background\"]};\n    height: 100%;\n    user-select: none;\n    cursor: default;\n\n    animation: ${EntranceKeyframes} 0.25s ease-in forwards;\n\n    display: flex;\n    flex-direction: column;\n`\n\nexport interface ISidebarHeaderProps {\n    // True if the pane has focus, false otherwise\n    hasFocus: boolean\n\n    headerName: string\n}\n\nexport const SidebarHeaderWrapper = withProps<ISidebarHeaderProps>(styled.div)`\n    height: 2.5em;\n    line-height: 2.5em;\n    text-align: center;\n    border-top: ${props =>\n        props.hasFocus\n            ? \"2px solid \" + props.theme[\"highlight.mode.normal.background\"]\n            : \"2px solid transparent\"};\n\n    flex: 0 0 auto;\n`\n\nexport class SidebarHeaderView extends React.PureComponent<ISidebarHeaderProps, {}> {\n    public render(): JSX.Element {\n        return (\n            <SidebarHeaderWrapper {...this.props} key={this.props.headerName}>\n                <span>{this.props.headerName}</span>\n            </SidebarHeaderWrapper>\n        )\n    }\n}\n\nexport const SidebarInnerPaneWrapper = withProps<{}>(styled.div)`\n    flex: 1 1 auto;\n    position: relative;\n    height: 100%;\n`\n\nexport class SidebarContentView extends React.PureComponent<\n    ISidebarContentViewProps,\n    ISidebarContentViewState\n> {\n    private _subs: IDisposable[] = []\n\n    constructor(props: ISidebarContentViewProps) {\n        super(props)\n        this.state = {\n            active: false,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._cleanSubscriptions()\n        const s1 = this.props.onEnter.subscribe(() =>\n            this.setState({\n                active: true,\n            }),\n        )\n\n        const s2 = this.props.onLeave.subscribe(() =>\n            this.setState({\n                active: false,\n            }),\n        )\n\n        this._subs = [s1, s2]\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanSubscriptions()\n    }\n\n    public render(): JSX.Element {\n        if (!this.props.activeEntry) {\n            return null\n        }\n\n        const activeEntry = this.props.activeEntry\n        const header = activeEntry && activeEntry.pane ? activeEntry.pane.title : null\n\n        return (\n            <SidebarContentWrapper className=\"sidebar-content\" width={this.props.width}>\n                <SidebarHeaderView hasFocus={this.state.active} headerName={header} />\n                <SidebarInnerPaneWrapper key={activeEntry.id}>\n                    {activeEntry.pane.render()}\n                </SidebarInnerPaneWrapper>\n            </SidebarContentWrapper>\n        )\n    }\n\n    private _cleanSubscriptions(): void {\n        this._subs.forEach(s => s.dispose())\n        this._subs = []\n    }\n}\n\nexport const mapStateToProps = (\n    state: ISidebarState,\n    containerProps: ISidebarContentContainerProps,\n): ISidebarContentViewProps => {\n    const activeEntry = getActiveEntry(state)\n    return {\n        ...containerProps,\n        activeEntry,\n        width: state.width,\n    }\n}\n\nexport const SidebarContent = connect(mapStateToProps)(SidebarContentView)\n"
  },
  {
    "path": "browser/src/Services/Sidebar/SidebarSplit.tsx",
    "content": "/**\r\n * UI/index.tsx\r\n *\r\n * Root setup & state for the UI\r\n * - Top-level render function lives here\r\n */\r\n\r\nimport * as React from \"react\"\r\nimport { Provider } from \"react-redux\"\r\n\r\nimport { SidebarManager } from \"./SidebarStore\"\r\nimport { Sidebar } from \"./SidebarView\"\r\n\r\nexport class SidebarSplit {\r\n    constructor(private _sidebarManager: SidebarManager) {}\r\n\r\n    public enter(): void {\r\n        this._sidebarManager.setActiveEntry(this._sidebarManager.activeEntryId)\r\n        this._sidebarManager.enter()\r\n    }\r\n\r\n    public leave(): void {\r\n        this._sidebarManager.setActiveEntry(null)\r\n        this._sidebarManager.leave()\r\n    }\r\n\r\n    public render(): JSX.Element {\r\n        return (\r\n            <Provider store={this._sidebarManager.store}>\r\n                <Sidebar onSelectionChanged={val => this._onSelectionChanged(val)} />\r\n            </Provider>\r\n        )\r\n    }\r\n\r\n    private _onSelectionChanged(newVal: string): void {\r\n        this._sidebarManager.setActiveEntry(newVal)\r\n    }\r\n}\r\n"
  },
  {
    "path": "browser/src/Services/Sidebar/SidebarStore.ts",
    "content": "/**\n * SidebarStore.ts\n *\n * State management for the sidebar split\n */\n\nimport { Reducer, Store } from \"redux\"\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nimport { Configuration } from \"../Configuration\"\nimport { DefaultConfiguration } from \"../Configuration/DefaultConfiguration\"\nimport { WindowManager, WindowSplitHandle } from \"./../WindowManager\"\nimport { SidebarContentSplit } from \"./SidebarContentSplit\"\nimport { SidebarSplit } from \"./SidebarSplit\"\n\nimport * as Oni from \"oni-api\"\n\nexport interface ISidebarState {\n    entries: ISidebarEntry[]\n\n    // Active means that the tab is currently selected\n    activeEntryId: string\n\n    isActive: boolean\n\n    width: string\n}\n\nexport type SidebarIcon = string\n\nexport interface ISidebarEntry {\n    // TODO: Remove this, duplicated between here and `SidebarPane`\n    id: string\n    icon: SidebarIcon\n    pane: SidebarPane\n    hasNotification?: boolean\n}\n\nexport interface SidebarPane extends Oni.IWindowSplit {\n    id: string\n    title: string\n\n    enter(): void\n    leave(): void\n}\n\nexport class SidebarManager {\n    private _store: Store<ISidebarState>\n\n    private _iconSplit: WindowSplitHandle\n    private _contentSplit: WindowSplitHandle\n\n    public get activeEntryId(): string {\n        return this._store.getState().activeEntryId\n    }\n\n    public get entries(): ISidebarEntry[] {\n        return this._store.getState().entries\n    }\n\n    get isFocused(): boolean {\n        return this._contentSplit.isFocused\n    }\n\n    get isVisible(): boolean {\n        return this._contentSplit.isVisible\n    }\n\n    public get store(): Store<ISidebarState> {\n        return this._store\n    }\n\n    constructor(\n        private _windowManager: WindowManager = null,\n        private _configuration: Configuration,\n    ) {\n        this._store = createStore()\n\n        this._configuration.onConfigurationChanged.subscribe(val => {\n            if (typeof val[\"sidebar.width\"] === \"string\") {\n                this.setWidth(val[\"sidebar.width\"])\n            }\n        })\n\n        this.setWidth(this._configuration.getValue(\"sidebar.width\"))\n\n        this._iconSplit = this._windowManager.createSplit(\"left\", new SidebarSplit(this))\n        this._contentSplit = this._windowManager.createSplit(\"left\", new SidebarContentSplit(this))\n    }\n\n    public increaseWidth(): void {\n        if (this._contentSplit.isVisible) {\n            this.store.dispatch({ type: \"INCREASE_WIDTH\" })\n        }\n    }\n\n    public decreaseWidth(): void {\n        if (this._contentSplit.isVisible) {\n            this.store.dispatch({ type: \"DECREASE_WIDTH\" })\n        }\n    }\n\n    public setWidth(width: string): void {\n        if (width) {\n            this._store.dispatch({\n                type: \"SET_WIDTH\",\n                width,\n            })\n        }\n    }\n\n    public setNotification(id: string): void {\n        if (id) {\n            this._store.dispatch({\n                type: \"SET_NOTIFICATION\",\n                id,\n            })\n        }\n    }\n\n    public setActiveEntry(id: string): void {\n        if (id) {\n            const oldId = this._store.getState().activeEntryId\n\n            this._store.dispatch({\n                type: \"SET_ACTIVE_ID\",\n                activeEntryId: id,\n            })\n\n            if (oldId !== id) {\n                this._contentSplit.show()\n            } else if (!this._contentSplit.isVisible) {\n                this._contentSplit.show()\n            } else if (this._contentSplit.isVisible) {\n                this._contentSplit.hide()\n            }\n        }\n    }\n\n    public focusContents(): void {\n        if (this._contentSplit.isVisible) {\n            this._contentSplit.focus()\n        }\n    }\n\n    public toggleSidebarVisibility(): void {\n        if (this._contentSplit.isVisible) {\n            this._contentSplit.hide()\n\n            if (this._contentSplit.isFocused) {\n                this._iconSplit.focus()\n            }\n        } else {\n            this._contentSplit.show()\n        }\n    }\n\n    public toggleVisibilityById(id: string): void {\n        if (id) {\n            if (id !== this.activeEntryId) {\n                this._store.dispatch({\n                    type: \"SET_ACTIVE_ID\",\n                    activeEntryId: id,\n                })\n\n                this._contentSplit.show()\n                this._contentSplit.focus()\n            } else {\n                if (this._contentSplit.isVisible) {\n                    this._contentSplit.hide()\n                } else {\n                    // In some cases you can have an ACTIVE entry that is hidden\n                    this._contentSplit.show()\n                    this._contentSplit.focus()\n                }\n            }\n        }\n    }\n\n    public enter(): void {\n        this._store.dispatch({ type: \"ENTER\" })\n    }\n\n    public leave(): void {\n        this._store.dispatch({ type: \"LEAVE\" })\n    }\n\n    public add(icon: SidebarIcon, pane: SidebarPane): void {\n        const entry = {\n            id: pane.id,\n            icon,\n            pane,\n        }\n        this._store.dispatch({\n            type: \"ADD_ENTRY\",\n            entry,\n        })\n    }\n\n    public hide(): void {\n        this._contentSplit.hide()\n        this._iconSplit.hide()\n    }\n}\n\nconst DefaultSidebarState: ISidebarState = {\n    entries: [],\n    activeEntryId: null,\n    isActive: false,\n    width: null,\n}\n\nexport type SidebarActions =\n    | {\n          type: \"SET_ACTIVE_ID\"\n          activeEntryId: string\n      }\n    | {\n          type: \"ADD_ENTRY\"\n          entry: ISidebarEntry\n      }\n    | {\n          type: \"SET_NOTIFICATION\"\n          id: string\n      }\n    | {\n          type: \"SET_WIDTH\"\n          width: string\n      }\n    | {\n          type: \"ENTER\"\n      }\n    | {\n          type: \"LEAVE\"\n      }\n    | {\n          type: \"INCREASE_WIDTH\"\n      }\n    | {\n          type: \"DECREASE_WIDTH\"\n      }\n\nexport const changeSize = (change: \"increase\" | \"decrease\") => (\n    size: string,\n    defaultValue = DefaultConfiguration[\"sidebar.width\"],\n): string => {\n    const [numberString, letters = \"em\"] = size.match(/[a-zA-Z]+|[0-9]+/g)\n    const isAllowedUnit = [\"em\", \"px\", \"vw\"].includes(letters)\n    const unitsToUse = isAllowedUnit ? letters : \"em\"\n    const convertedNumber = Number(numberString)\n    if (isNaN(convertedNumber)) {\n        return defaultValue\n    }\n\n    // If too small don't allow a decrease and vice versa\n    const tooSmall = convertedNumber - 1 < 1 && change === \"decrease\"\n    const tooBig = convertedNumber + 1 > 50 && change === \"increase\"\n\n    const changed =\n        tooBig || tooSmall\n            ? convertedNumber\n            : change === \"increase\"\n                ? convertedNumber + 1\n                : convertedNumber - 1\n\n    return `${changed}${unitsToUse}`\n}\n\nexport const increaseWidth = changeSize(\"increase\")\nexport const decreaseWidth = changeSize(\"decrease\")\n\nexport const sidebarReducer: Reducer<ISidebarState> = (\n    state: ISidebarState = DefaultSidebarState,\n    action: SidebarActions,\n) => {\n    const newState = {\n        ...state,\n        entries: entriesReducer(state.entries, action),\n    }\n\n    switch (action.type) {\n        case \"ENTER\":\n            return {\n                ...newState,\n                isActive: true,\n            }\n        case \"LEAVE\":\n            return {\n                ...newState,\n                isActive: false,\n            }\n        case \"SET_WIDTH\":\n            return {\n                ...newState,\n                width: action.width,\n            }\n        case \"SET_ACTIVE_ID\":\n            return {\n                ...newState,\n                activeEntryId: action.activeEntryId,\n            }\n        case \"ADD_ENTRY\":\n            if (!state.activeEntryId) {\n                return {\n                    ...newState,\n                    activeEntryId: action.entry.pane.id,\n                }\n            } else {\n                return newState\n            }\n        case \"DECREASE_WIDTH\":\n            return {\n                ...newState,\n                width: decreaseWidth(newState.width),\n            }\n        case \"INCREASE_WIDTH\":\n            return {\n                ...newState,\n                width: increaseWidth(newState.width),\n            }\n        default:\n            return newState\n    }\n}\n\nexport const entriesReducer: Reducer<ISidebarEntry[]> = (\n    state: ISidebarEntry[] = [],\n    action: SidebarActions,\n) => {\n    switch (action.type) {\n        case \"ADD_ENTRY\":\n            return [...state, action.entry]\n        case \"SET_ACTIVE_ID\":\n            return state.map(e => {\n                if (e.id === action.activeEntryId) {\n                    return {\n                        ...e,\n                        hasNotification: false,\n                    }\n                } else {\n                    return e\n                }\n            })\n        case \"SET_NOTIFICATION\":\n            return state.map(e => {\n                if (e.id !== action.id) {\n                    return e\n                } else {\n                    return {\n                        ...e,\n                        hasNotification: true,\n                    }\n                }\n            })\n        default:\n            return state\n    }\n}\n\nexport const createStore = (): Store<ISidebarState> => {\n    return createReduxStore(\"Sidebar\", sidebarReducer, DefaultSidebarState)\n}\n"
  },
  {
    "path": "browser/src/Services/Sidebar/SidebarView.tsx",
    "content": "/**\n * SidebarView.tsx\n *\n * View component for the sidebar\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport { Icon, IconSize } from \"./../../UI/Icon\"\n\nimport { ISidebarEntry, ISidebarState } from \"./SidebarStore\"\n\nimport styled, { keyframes } from \"styled-components\"\nimport { withProps } from \"./../../UI/components/common\"\n\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\n\nexport interface ISidebarIconProps {\n    id: string\n    active: boolean\n    focused: boolean\n    iconName: string\n    hasNotification: boolean\n    onClick: () => void\n}\n\nimport { VimNavigator } from \"./../../UI/components/VimNavigator\"\n\nconst EntranceKeyframes = keyframes`\n    0% { opacity: 0.5; transform: scale(0.5) translateX(-10px); }\n    100%% { opacity: 1; transform: scale(1.0) translateX(0px); }\n`\n\nconst SidebarIconWrapper = withProps<ISidebarIconProps>(styled.div)`\n    position: relative;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    opacity: 0.5;\n    outline: none;\n    cursor: pointer;\n    opacity: ${props => (props.active ? 0.9 : 0.75)};\n    border-left: 2px solid ${props =>\n        props.focused ? props.theme[\"sidebar.selection.border\"] : \"transparent\"};\n    background-color: ${props =>\n        props.active ? props.theme[\"editor.background\"] : props.theme.background};\n    transition: transform 0.2s ease-in;\n    transform: ${props => (props.active || props.focused ? \"translateY(0px)\" : \"translateY(0px)\")};\n\n    animation: ${EntranceKeyframes} 0.1s ease-in forwards;\n\n    &.active {\n        opacity: 0.75;\n    }\n\n    &:hover {\n        transform: translateY(0px);\n        opacity: 0.9;\n    }\n    `\n\nconst NotificationEnterKeyFrames = keyframes`\n    0% { opacity: 0; transform: scale(0.5); translateY(6px); }\n    75% { opacity: 0.75; transform: scale(1.25); translateY(2px); }\n    100% { opacity: 1; transform: scale(1); translateY(0px); }\n`\n\nconst SidebarIconNotification = withProps<{}>(styled.div)`\n    animation: ${NotificationEnterKeyFrames} 0.35s linear forwards;\n    animation-delay: 1s;\n\n    opacity: 0;\n\n    position:absolute;\n    top: 10px;\n    right: 10px;\n    width: 0.4rem;\n    height: 0.4rem;\n\n    background-color: ${p => p.theme[\"highlight.mode.normal.background\"]};\n    border-radius: 1rem;\n`\n\nconst SidebarIconInner = styled.div`\n    margin-top: 16px;\n    margin-bottom: 16px;\n`\n\nexport class SidebarIcon extends React.PureComponent<ISidebarIconProps, {}> {\n    public render(): JSX.Element {\n        const notification = this.props.hasNotification ? <SidebarIconNotification /> : null\n        return (\n            <Sneakable callback={this.props.onClick} tag={this.props.id}>\n                <SidebarIconWrapper {...this.props} tabIndex={0}>\n                    <SidebarIconInner>\n                        <Icon name={this.props.iconName} size={IconSize.Large} />\n                    </SidebarIconInner>\n                    {notification}\n                </SidebarIconWrapper>\n            </Sneakable>\n        )\n    }\n}\n\nexport interface ISidebarViewProps extends ISidebarContainerProps {\n    width: string\n    visible: boolean\n    entries: ISidebarEntry[]\n    activeEntryId: string\n    isActive: boolean\n}\n\nexport interface ISidebarContainerProps {\n    onSelectionChanged: (selectedId: string) => void\n}\n\nexport interface ISidebarWrapperProps {\n    width: string\n    isActive: boolean\n}\n\nconst SidebarWrapper = withProps<ISidebarWrapperProps>(styled.div)`\n    pointer-events: auto;\n\n    display: flex;\n    flex-direction: column;\n\n    border-top: ${props =>\n        props.isActive\n            ? \"2px solid \" + props.theme[\"highlight.mode.normal.background\"]\n            : \"2px solid \" + props.theme[\"editor.background\"]};\n\n    color: ${props => props.theme[\"sidebar.foreground\"]};\n    width: ${props => props.width};\n`\n\nexport class SidebarView extends React.PureComponent<ISidebarViewProps, {}> {\n    public render(): JSX.Element {\n        if (!this.props.visible) {\n            return null\n        }\n\n        const ids = this.props.entries.map(e => e.id)\n\n        return (\n            <SidebarWrapper width={this.props.width} isActive={this.props.isActive}>\n                <VimNavigator\n                    ids={ids}\n                    active={this.props.isActive}\n                    onSelectionChanged={val => this.props.onSelectionChanged(val)}\n                    render={(selectedId: string): JSX.Element => {\n                        const items = this.props.entries.map(e => {\n                            const isActive = e.id === this.props.activeEntryId\n                            const isFocused = e.id === selectedId && this.props.isActive\n                            return (\n                                <SidebarIcon\n                                    id={e.id}\n                                    key={e.id}\n                                    iconName={e.icon}\n                                    active={isActive}\n                                    focused={isFocused}\n                                    hasNotification={e.hasNotification}\n                                    onClick={() => this.props.onSelectionChanged(e.id)}\n                                />\n                            )\n                        })\n                        return <div className=\"icons\">{items}</div>\n                    }}\n                />\n            </SidebarWrapper>\n        )\n    }\n}\n\nexport const mapStateToProps = (\n    state: ISidebarState,\n    containerProps: ISidebarContainerProps,\n): ISidebarViewProps => {\n    return {\n        ...containerProps,\n        entries: state.entries,\n        activeEntryId: state.activeEntryId,\n        isActive: state.isActive,\n        visible: true,\n        width: \"50px\",\n    }\n}\n\nexport const Sidebar = connect(mapStateToProps)(SidebarView)\n"
  },
  {
    "path": "browser/src/Services/Sidebar/index.ts",
    "content": "import { commandManager } from \"./../../Services/CommandManager\"\nimport { Configuration } from \"./../../Services/Configuration\"\nimport { windowManager } from \"./../../Services/WindowManager\"\nimport { Workspace } from \"./../../Services/Workspace\"\n\nimport { SidebarManager } from \"./SidebarStore\"\n\nlet _sidebarManager: SidebarManager = null\n\nexport * from \"./SidebarStore\"\n\nexport const activate = (configuration: Configuration, workspace: Workspace) => {\n    // Always create the sidebar to prevent issues. If its disabled, just hide it.\n    // See #1562 for more information.\n    _sidebarManager = new SidebarManager(windowManager, configuration)\n\n    const sideBarEnabled = configuration.getValue(\"sidebar.enabled\")\n\n    if (!sideBarEnabled) {\n        _sidebarManager.hide()\n    }\n\n    if (sideBarEnabled && !configuration.getValue(\"sidebar.default.open\")) {\n        _sidebarManager.toggleSidebarVisibility()\n    }\n\n    commandManager.registerCommand({\n        command: \"sidebar.increaseWidth\",\n        name: \"Sidebar: Increase Width\",\n        detail: \"Increase the width of the sidebar pane\",\n        execute: () => _sidebarManager.increaseWidth(),\n    })\n\n    commandManager.registerCommand({\n        command: \"sidebar.decreaseWidth\",\n        name: \"Sidebar: Decrease Width\",\n        detail: \"Decrease the width of the sidebar pane\",\n        execute: () => _sidebarManager.decreaseWidth(),\n    })\n\n    commandManager.registerCommand({\n        command: \"sidebar.toggle\",\n        name: \"Sidebar: Toggle\",\n        detail: \"Show / hide the contents of the sidebar pane.\",\n        execute: () => _sidebarManager.toggleSidebarVisibility(),\n    })\n}\n\nexport const getInstance = (): SidebarManager => _sidebarManager\n"
  },
  {
    "path": "browser/src/Services/Sneak/Sneak.tsx",
    "content": "/**\n * Sneak.tsx\n *\n * Provides the 'sneak layer' UI\n */\n\nimport * as React from \"react\"\nimport { Provider } from \"react-redux\"\nimport { Store } from \"redux\"\n\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { Overlay, OverlayManager } from \"./../Overlay\"\n\nimport {\n    createStore as createSneakStore,\n    IAugmentedSneakInfo,\n    ISneakInfo,\n    ISneakState,\n} from \"./SneakStore\"\nimport { ConnectedSneakView } from \"./SneakView\"\n\nexport type SneakProvider = () => Promise<ISneakInfo[]>\n\nexport class Sneak {\n    private _activeOverlay: Overlay\n    private _providers: SneakProvider[] = []\n    private _store: Store<ISneakState>\n    private _onSneakCompleted = new Event<ISneakInfo>()\n\n    public get onSneakCompleted(): IEvent<ISneakInfo> {\n        return this._onSneakCompleted\n    }\n\n    constructor(private _overlayManager: OverlayManager) {\n        this._store = createSneakStore()\n    }\n\n    public get isActive(): boolean {\n        return !!this._activeOverlay\n    }\n\n    public addSneakProvider(provider: SneakProvider): IDisposable {\n        this._providers.push(provider)\n        const dispose = () => (this._providers = this._providers.filter(prov => prov !== provider))\n        return { dispose }\n    }\n\n    // Get the first sneak with a 'tag' matching the passed in tag\n    public getSneakMatchingTag(tag: string): IAugmentedSneakInfo | null {\n        if (!this.isActive) {\n            return null\n        }\n\n        const sneaks = this._store.getState().sneaks\n\n        if (!sneaks || sneaks.length === 0) {\n            return null\n        }\n\n        return sneaks.find(s => s.tag && s.tag === tag)\n    }\n\n    public show(): void {\n        if (this._activeOverlay) {\n            this._activeOverlay.hide()\n            this._activeOverlay = null\n        }\n\n        this._store.dispatch({\n            type: \"START\",\n            width: document.body.offsetWidth,\n            height: document.body.offsetHeight,\n        })\n        this._collectSneakRectangles()\n\n        this._activeOverlay = this._overlayManager.createItem()\n\n        this._activeOverlay.setContents(\n            <Provider store={this._store}>\n                <ConnectedSneakView onComplete={info => this._onComplete(info)} />\n            </Provider>,\n        )\n        this._activeOverlay.show()\n    }\n\n    public close(): void {\n        if (this._activeOverlay) {\n            this._store.dispatch({ type: \"END\" })\n            this._activeOverlay.hide()\n            this._activeOverlay = null\n        }\n    }\n\n    private _onComplete(sneakInfo: ISneakInfo): void {\n        this.close()\n        sneakInfo.callback()\n\n        this._onSneakCompleted.dispatch(sneakInfo)\n    }\n\n    private _collectSneakRectangles(): void {\n        this._providers.forEach(async provider => {\n            const sneaks = await provider()\n            const normalizedSneaks = sneaks.filter(s => !!s)\n            this._store.dispatch({\n                type: \"ADD_SNEAKS\",\n                sneaks: normalizedSneaks,\n            })\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Sneak/SneakStore.ts",
    "content": "/**\n * SneakStore.ts\n *\n * State management for Sneaks\n */\n\nimport { Reducer, Store } from \"redux\"\n\nimport { Shapes } from \"oni-api\"\n\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nexport interface ISneakInfo {\n    rectangle: Shapes.Rectangle\n    callback: () => void\n\n    // `tag` is an optional string used to identify the sneak\n    tag?: string\n}\n\nexport interface IAugmentedSneakInfo extends ISneakInfo {\n    triggerKeys: string\n}\n\nexport interface ISneakState {\n    isActive: boolean\n    sneaks: IAugmentedSneakInfo[]\n    width: number\n    height: number\n}\n\nconst DefaultSneakState: ISneakState = {\n    isActive: true,\n    sneaks: [],\n    width: 0,\n    height: 0,\n}\n\nexport type SneakAction =\n    | {\n          type: \"START\"\n          width: number\n          height: number\n      }\n    | {\n          type: \"END\"\n      }\n    | {\n          type: \"ADD_SNEAKS\"\n          sneaks: ISneakInfo[]\n      }\n\nexport const sneakReducer: Reducer<ISneakState> = (\n    state: ISneakState = DefaultSneakState,\n    action: SneakAction,\n) => {\n    switch (action.type) {\n        case \"START\":\n            return {\n                ...DefaultSneakState,\n                width: action.width,\n                height: action.height,\n            }\n        case \"END\":\n            return {\n                ...DefaultSneakState,\n                isActive: false,\n            }\n        case \"ADD_SNEAKS\":\n            if (!state.isActive) {\n                return state\n            }\n\n            const filteredSneaks = action.sneaks.filter(sneak => {\n                const { x, y } = sneak.rectangle\n                return x >= 0 && y >= 0 && x < state.width && y < state.height\n            })\n\n            const newSneaks: IAugmentedSneakInfo[] = filteredSneaks.map((sneak, idx) => {\n                return {\n                    ...sneak,\n                    triggerKeys: getLabelFromIndex(idx + state.sneaks.length),\n                }\n            })\n\n            return {\n                ...state,\n                sneaks: [...state.sneaks, ...newSneaks],\n            }\n        default:\n            return state\n    }\n}\n\nexport const getLabelFromIndex = (index: number): string => {\n    const firstDigit = Math.floor(index / 26)\n    const secondDigit = index - firstDigit * 26\n    return String.fromCharCode(97 + firstDigit, 97 + secondDigit).toUpperCase()\n}\n\nexport const createStore = (): Store<ISneakState> => {\n    return createReduxStore(\"Sneaks\", sneakReducer, DefaultSneakState)\n}\n"
  },
  {
    "path": "browser/src/Services/Sneak/SneakView.tsx",
    "content": "/**\n * SneakView.tsx\n *\n * UX for the sneak functionality\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport { boxShadow, OverlayWrapper } from \"./../../UI/components/common\"\nimport { TextInputView } from \"./../../UI/components/LightweightText\"\n\nimport { IAugmentedSneakInfo, ISneakInfo, ISneakState } from \"./SneakStore\"\n\nexport interface ISneakContainerProps {\n    onComplete: (sneakInfo: ISneakInfo) => void\n}\n\nexport interface ISneakViewProps extends ISneakContainerProps {\n    sneaks: IAugmentedSneakInfo[]\n}\n\nexport interface ISneakViewState {\n    filterText: string\n}\n\n// Render a keyboard input?\n// Grab input while 'sneaking'?\nexport class SneakView extends React.PureComponent<ISneakViewProps, ISneakViewState> {\n    constructor(props: ISneakViewProps) {\n        super(props)\n\n        this.state = {\n            filterText: \"\",\n        }\n    }\n\n    public render(): JSX.Element {\n        const normalizedFilterText = this.state.filterText.toUpperCase()\n        const filteredSneaks = this.props.sneaks.filter(\n            sneak => sneak.triggerKeys.indexOf(normalizedFilterText) === 0,\n        )\n        const sneaks = filteredSneaks.map(si => (\n            <SneakItemView\n                sneak={si}\n                filterLength={normalizedFilterText.length}\n                key={si.triggerKeys}\n            />\n        ))\n\n        if (filteredSneaks.length === 1) {\n            this.props.onComplete(filteredSneaks[0])\n        }\n\n        return (\n            <OverlayWrapper style={{ backgroundColor: \"rgba(0, 0, 0, 0.1)\" }}>\n                <div style={{ opacity: 0.01 }}>\n                    <TextInputView\n                        onChange={evt => {\n                            this.setState({ filterText: evt.currentTarget.value })\n                        }}\n                    />\n                </div>\n                {sneaks}\n            </OverlayWrapper>\n        )\n    }\n}\n\nexport interface ISneakItemViewProps {\n    sneak: IAugmentedSneakInfo\n    filterLength: number\n}\n\nimport styled, { keyframes } from \"styled-components\"\n\nconst SneakEnterKeyFrames = keyframes`\n    0% { opacity: 0; transform: scale(0.9) translateY(-5px) rotateX(-70deg); }\n    100%% { opacity: 1; transform: scale(1.0) translateY(0px) rotateX(0deg); }\n`\n\nconst SneakItemWrapper = styled.div`\n    ${boxShadow} background-color: ${props => props.theme[\"highlight.mode.visual.background\"]};\n    color: ${props => props.theme[\"highlight.mode.visual.foreground\"]};\n    animation: ${SneakEnterKeyFrames} 0.2s ease-in;\n    text-align: center;\n`\n\nconst SneakItemViewSize = 22\nconst px = (num: number): string => num.toString() + \"px\"\nexport class SneakItemView extends React.PureComponent<ISneakItemViewProps, {}> {\n    public render(): JSX.Element {\n        const style: React.CSSProperties = {\n            position: \"absolute\",\n            left: px(this.props.sneak.rectangle.x),\n            top: px(this.props.sneak.rectangle.y),\n            width: px(SneakItemViewSize),\n            height: px(SneakItemViewSize),\n        }\n\n        return (\n            <SneakItemWrapper style={style}>\n                <span style={{ fontWeight: \"bold\" }}>\n                    {this.props.sneak.triggerKeys.substring(0, this.props.filterLength)}\n                </span>\n                <span>\n                    {this.props.sneak.triggerKeys.substring(\n                        this.props.filterLength,\n                        this.props.sneak.triggerKeys.length,\n                    )}\n                </span>\n            </SneakItemWrapper>\n        )\n    }\n}\n\nconst mapStateToProps = (\n    state: ISneakState,\n    containerProps?: ISneakContainerProps,\n): ISneakViewProps => {\n    return {\n        ...containerProps,\n        sneaks: state.sneaks || [],\n    }\n}\n\nexport const ConnectedSneakView = connect(mapStateToProps)(SneakView)\n"
  },
  {
    "path": "browser/src/Services/Sneak/index.tsx",
    "content": "/**\n * Sneak/index.tsx\n *\n * Entry point for sneak functionality\n */\n\nimport { Colors } from \"./../Colors\"\nimport { CallbackCommand, CommandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { AchievementsManager } from \"./../Learning/Achievements\"\nimport { OverlayManager } from \"./../Overlay\"\nimport { getInstance as getParticlesInstance } from \"./../Particles\"\n\nimport { Sneak } from \"./Sneak\"\n\nexport * from \"./SneakStore\"\n\nlet _sneak: Sneak\n\nexport const activate = (\n    colors: Colors,\n    commandManager: CommandManager,\n    configuration: Configuration,\n    overlayManager: OverlayManager,\n) => {\n    _sneak = new Sneak(overlayManager)\n\n    commandManager.registerCommand(\n        new CallbackCommand(\n            \"sneak.show\",\n            \"Sneak: Current Window\",\n            \"Show commands for current window\",\n            () => {\n                _sneak.show()\n            },\n        ),\n    )\n\n    commandManager.registerCommand(\n        new CallbackCommand(\n            \"sneak.hide\",\n            \"Sneak: Hide\",\n            \"Hide sneak view\",\n            () => _sneak.close(),\n            () => _sneak.isActive,\n        ),\n    )\n\n    initializeParticles(colors, configuration)\n}\n\nexport const registerAchievements = (achievements: AchievementsManager) => {\n    achievements.registerAchievement({\n        uniqueId: \"oni.achievement.sneak.1\",\n        name: \"Sneaky\",\n        description: \"Use the 'sneak' functionality for the first time\",\n        goals: [\n            {\n                name: null,\n                goalId: \"oni.goal.sneak.complete\",\n                count: 1,\n            },\n        ],\n    })\n\n    _sneak.onSneakCompleted.subscribe(val => {\n        achievements.notifyGoal(\"oni.goal.sneak.complete\")\n    })\n}\n\nexport const initializeParticles = (colors: Colors, configuration: Configuration) => {\n    const isAnimationEnabled = () => configuration.getValue(\"ui.animations.enabled\")\n    const getVisualColor = () => colors.getColor(\"highlight.mode.visual.background\")\n\n    _sneak.onSneakCompleted.subscribe(sneak => {\n        if (!isAnimationEnabled()) {\n            return\n        }\n        const particles = getParticlesInstance()\n\n        if (!particles) {\n            return\n        }\n\n        particles.createParticles(15, {\n            Position: { x: sneak.rectangle.x, y: sneak.rectangle.y },\n            PositionVariance: { x: 0, y: 0 },\n            Velocity: { x: 0, y: 0 },\n            Gravity: { x: 0, y: 300 },\n            VelocityVariance: { x: 200, y: 200 },\n            Time: 0.2,\n            Color: getVisualColor(),\n        })\n    })\n}\n\nexport const getInstance = (): Sneak => {\n    return _sneak\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/OniSnippet.ts",
    "content": "/**\n * OniSnippet.ts\n *\n * Wrapper around `TextmateSnippet`. There are some differences in behavior\n * due to differences in editor behavior, for Oni/Neovim, we need to\n * get the snippet split by new lines, with placeholders per line/character\n * instead of by offset.\n */\n\nimport * as Snippets from \"vscode-snippet-parser/lib\"\nimport { normalizeNewLines } from \"./../../Utility\"\n\nexport type VariableResolver = Snippets.VariableResolver\nexport type Variable = Snippets.Variable\n\nexport interface OniSnippetPlaceholder {\n    index: number\n\n    // Zero-based line relative to the start of the snippet\n    line: number\n\n    // Zero-based start character\n    character: number\n\n    value: string\n\n    isFinalTabstop: boolean\n}\n\nexport const getLineCharacterFromOffset = (\n    offset: number,\n    lines: string[],\n): { line: number; character: number } => {\n    let idx = 0\n    let currentOffset = 0\n    while (idx < lines.length) {\n        if (offset >= currentOffset && offset <= currentOffset + lines[idx].length) {\n            return { line: idx, character: offset - currentOffset }\n        }\n\n        currentOffset += lines[idx].length + 1\n        idx++\n    }\n\n    return { line: -1, character: -1 }\n}\n\nexport class OniSnippet {\n    private _parser: Snippets.SnippetParser = new Snippets.SnippetParser()\n    private _placeholderValues: { [index: number]: string } = {}\n    private _snippetString: string\n\n    constructor(snippet: string, private _variableResolver?: VariableResolver) {\n        this._snippetString = normalizeNewLines(snippet)\n    }\n\n    public setPlaceholder(index: number, newValue: string): void {\n        this._placeholderValues[index] = newValue\n    }\n\n    public getPlaceholderValue(index: number): string {\n        return this._placeholderValues[index] || \"\"\n    }\n\n    public getPlaceholders(): OniSnippetPlaceholder[] {\n        const snippet = this._getSnippetWithFilledPlaceholders()\n        const placeholders = snippet.placeholders\n\n        const lines = this.getLines()\n\n        const oniPlaceholders = placeholders.map(p => {\n            const offset = snippet.offset(p)\n            const position = getLineCharacterFromOffset(offset, lines)\n\n            return {\n                ...position,\n                index: p.index,\n                value: p.toString(),\n                isFinalTabstop: p.isFinalTabstop,\n            }\n        })\n\n        return oniPlaceholders\n    }\n\n    public getLines(): string[] {\n        const normalizedSnippetString = this._getNormalizedSnippet()\n\n        return normalizedSnippetString.split(\"\\n\")\n    }\n\n    private _getSnippetWithFilledPlaceholders(): Snippets.TextmateSnippet {\n        const snippet = this._parser.parse(this._snippetString)\n\n        if (this._variableResolver) {\n            snippet.resolveVariables(this._variableResolver)\n        }\n\n        Object.keys(this._placeholderValues).forEach((key: string) => {\n            const val = this._placeholderValues[key]\n            const snip = this._parser.parse(val)\n\n            const placeholderToReplace = snippet.placeholders.filter(\n                p => p.index.toString() === key,\n            )\n\n            placeholderToReplace.forEach(rep => {\n                const placeHolder = new Snippets.Placeholder(rep.index)\n                placeHolder.appendChild(snip)\n                snippet.replace(rep, [placeHolder])\n            })\n        })\n\n        return snippet\n    }\n\n    private _getNormalizedSnippet(): string {\n        const snippetString = this._getSnippetWithFilledPlaceholders().toString()\n        const normalizedSnippetString = snippetString.replace(\"\\r\\n\", \"\\n\")\n\n        return normalizedSnippetString\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/SnippetBufferLayer.tsx",
    "content": "/**\n * SnippetBufferLayer.tsx\n *\n * UX for the Snippet functionality, implemented as a buffer layer\n */\n\nimport * as React from \"react\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport * as Oni from \"oni-api\"\nimport { IDisposable } from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { SnippetSession } from \"./SnippetSession\"\n\nimport { withProps } from \"./../../UI/components/common\"\n\nexport class SnippetBufferLayer implements Oni.BufferLayer {\n    constructor(private _buffer: Oni.Buffer, private _snippetSession: SnippetSession) {\n        this._buffer.addLayer(this)\n    }\n\n    public get id(): string {\n        return \"oni.layers.snippet\"\n    }\n\n    public get friendlyName(): string {\n        return \"Snippet\"\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        return <SnippetBufferLayerView context={context} snippetSession={this._snippetSession} />\n    }\n\n    public dispose(): void {\n        if (this._buffer) {\n            ;(this._buffer as any).removeLayer(this)\n\n            this._buffer = null\n            this._snippetSession = null\n        }\n    }\n}\n\nexport interface ISnippetBufferLayerViewProps {\n    context: Oni.BufferLayerRenderContext\n    snippetSession: SnippetSession\n}\n\nconst EntranceKeyFrames = keyframes`\n    0% { opacity: 0; }\n    100% { opacity: 1; }\n`\n\nconst NonSnippetOverlayTop = styled.div`\n    animation: ${EntranceKeyFrames} 0.2s ease-in;\n    background-color: rgba(0, 0, 0, 0.1);\n    box-shadow: inset 0 -5px 10px rgba(0, 0, 0, 0.2);\n`\n\nconst NonSnippetOverlayBottom = styled.div`\n    animation: ${EntranceKeyFrames} 0.2s ease-in;\n    background-color: rgba(0, 0, 0, 0.1);\n    box-shadow: inset 0 5px 10px rgba(0, 0, 0, 0.2);\n`\n\nconst CursorWrapper = withProps<{}>(styled.div)`\n    position: absolute;\n    background-color: ${props => props.theme[\"editor.foreground\"]};\n`\n\nexport interface ISnippetBufferLayerViewState {\n    mode: Oni.Vim.Mode\n    cursors: types.Range[]\n}\n\nexport class SnippetBufferLayerView extends React.PureComponent<\n    ISnippetBufferLayerViewProps,\n    ISnippetBufferLayerViewState\n> {\n    private _disposables: IDisposable[] = []\n\n    constructor(props: ISnippetBufferLayerViewProps) {\n        super(props)\n\n        const latestCursorState = props.snippetSession.getLatestCursors()\n        this.state = {\n            mode: latestCursorState.mode,\n            cursors: latestCursorState.cursors,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._cleanup()\n\n        const s1 = this.props.snippetSession.onCursorMoved.subscribe(p => {\n            this.setState({\n                mode: p.mode,\n                cursors: p.cursors,\n            })\n        })\n\n        this._disposables = [s1]\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanup()\n    }\n\n    public render(): JSX.Element {\n        if (!this.props.context.screenToPixel || !this.props.context.bufferToScreen) {\n            return null\n        }\n\n        const fullScreenSize = this.props.context.dimensions\n\n        // Get screen size in pixel space\n        const fullSizeInPixels = this.props.context.screenToPixel({\n            screenX: fullScreenSize.width,\n            screenY: fullScreenSize.height,\n        })\n\n        const snippetStartPosition = this.props.snippetSession.position.line\n        const snippetEndPosition =\n            this.props.snippetSession.position.line + this.props.snippetSession.lines.length\n\n        const startScreenPosition = this.props.context.bufferToScreen(\n            types.Position.create(snippetStartPosition, 0),\n        )\n        const endScreenPosition = this.props.context.bufferToScreen(\n            types.Position.create(snippetEndPosition, 0),\n        )\n\n        if (!startScreenPosition || !endScreenPosition) {\n            return null\n        }\n\n        const startPositionInPixels = this.props.context.screenToPixel(startScreenPosition)\n        const endPositionInPixels = this.props.context.screenToPixel(endScreenPosition)\n\n        const topOverlay: React.CSSProperties = {\n            position: \"absolute\",\n            top: \"0px\",\n            left: \"0px\",\n            right: \"0px\",\n            height: startPositionInPixels.pixelY.toString() + \"px\",\n        }\n\n        const bottomOverlay: React.CSSProperties = {\n            position: \"absolute\",\n            height: (fullSizeInPixels.pixelY - endPositionInPixels.pixelY).toString() + \"px\",\n            left: \"0px\",\n            bottom: \"0px\",\n            right: \"0px\",\n        }\n\n        const cursors = this.state.cursors.map(c => {\n            const pos = this.props.context.screenToPixel(this.props.context.bufferToScreen(c.start))\n\n            const size = this.props.context.screenToPixel(this.props.context.bufferToScreen(c.end))\n\n            const style: React.CSSProperties = {\n                top: pos.pixelY.toString() + \"px\",\n                left: pos.pixelX.toString() + \"px\",\n                width:\n                    this.state.mode === \"visual\"\n                        ? (size.pixelX - pos.pixelX).toString() + \"px\"\n                        : \"2px\",\n                opacity: this.state.mode === \"visual\" ? 0.2 : 0.8,\n                // TODO: Add 'fontPixelWidth' and 'fontPixelHeight' as API methods\n                height: (this.props.context as any).fontPixelHeight.toString() + \"px\",\n            }\n\n            return <CursorWrapper style={style} />\n        })\n\n        return (\n            <div\n                style={{\n                    position: \"absolute\",\n                    top: \"0px\",\n                    bottom: \"0px\",\n                    left: \"0px\",\n                    right: \"0px\",\n                }}\n            >\n                <NonSnippetOverlayTop style={topOverlay} />\n                <NonSnippetOverlayBottom style={bottomOverlay} />\n                {cursors}\n            </div>\n        )\n    }\n\n    private _cleanup(): void {\n        this._disposables.forEach(d => d.dispose())\n\n        this._disposables = []\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/SnippetCompletionProvider.ts",
    "content": "/**\n * SnippetCompletionProvider.ts\n *\n * Integrates snippets with completion provider\n */\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { CompletionsRequestContext, ICompletionsRequestor } from \"./../Completion\"\nimport { SnippetManager } from \"./SnippetManager\"\n\nexport const convertSnippetToCompletionItem = (\n    snippet: Oni.Snippets.Snippet,\n): types.CompletionItem => ({\n    insertTextFormat: types.InsertTextFormat.Snippet,\n    insertText: snippet.body,\n    label: snippet.prefix + \" (snippet)\",\n    detail: snippet.description,\n    documentation: snippet.body,\n    kind: types.CompletionItemKind.Snippet,\n})\n\nexport class SnippetCompletionProvider implements ICompletionsRequestor {\n    constructor(private _snippetManager: SnippetManager) {}\n\n    public async getCompletions(\n        context: CompletionsRequestContext,\n    ): Promise<types.CompletionItem[]> {\n        Log.verbose(\"[SnippetCompletionProvider::getCompletions] Starting...\")\n\n        if (!context.meetCharacter) {\n            return []\n        }\n\n        const commentsOrQuotedStrings = context.textMateScopes.filter(\n            f => f.indexOf(\"comment.\") === 0 || f.indexOf(\"string.quoted.\") === 0,\n        )\n        if (commentsOrQuotedStrings.length) {\n            return []\n        }\n\n        const snippets = await this._snippetManager.getSnippetsForLanguage(context.language)\n        Log.verbose(\n            \"[SnippetCompletionProvider::getCompletions] Got \" + snippets.length + \" snippets.\",\n        )\n\n        const items = snippets.map(convertSnippetToCompletionItem)\n        return items\n    }\n\n    public async getCompletionDetails(\n        fileLanguage: string,\n        fielPath: string,\n        completionItem: types.CompletionItem,\n    ): Promise<types.CompletionItem> {\n        return completionItem\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/SnippetManager.ts",
    "content": "/**\n * Snippets.ts\n *\n * Manages snippet integration\n */\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { IDisposable } from \"oni-types\"\n\nimport \"rxjs/add/operator/auditTime\"\nimport { Subject } from \"rxjs/Subject\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\n\nimport { SnippetBufferLayer } from \"./SnippetBufferLayer\"\nimport { CompositeSnippetProvider } from \"./SnippetProvider\"\nimport { SnippetSession } from \"./SnippetSession\"\n\nexport class SnippetManager implements Oni.Snippets.SnippetManager {\n    private _activeSession: SnippetSession\n    private _disposables: IDisposable[] = []\n    private _currentLayer: SnippetBufferLayer = null\n\n    private _snippetProvider: CompositeSnippetProvider\n    private _synchronizeSnippetObservable: Subject<void> = new Subject<void>()\n\n    public get isSnippetActive(): boolean {\n        return !!this._activeSession\n    }\n\n    constructor(private _configuration: Configuration, private _editorManager: EditorManager) {\n        this._snippetProvider = new CompositeSnippetProvider(this._configuration)\n\n        this._synchronizeSnippetObservable.auditTime(50).subscribe(() => {\n            const activeEditor = this._editorManager.activeEditor as any\n            const activeSession = this._activeSession\n\n            if (activeEditor && activeSession) {\n                activeEditor.blockInput(() => activeSession.synchronizeUpdatedPlaceholders())\n            }\n        })\n    }\n\n    public async getSnippetsForLanguage(language: string): Promise<Oni.Snippets.Snippet[]> {\n        return this._snippetProvider.getSnippets(language)\n    }\n\n    public registerSnippetProvider(snippetProvider: Oni.Snippets.SnippetProvider): void {\n        this._snippetProvider.registerProvider(snippetProvider)\n    }\n\n    /**\n     * Inserts snippet in the active editor, at current cursor position\n     */\n    public async insertSnippet(snippet: string): Promise<void> {\n        this.cancel()\n        Log.info(\"[SnippetManager::insertSnippet]\")\n\n        const activeEditor = this._editorManager.activeEditor as any\n        const snippetSession = new SnippetSession(activeEditor as any, snippet)\n        await snippetSession.start()\n\n        const buffer = this._editorManager.activeEditor.activeBuffer\n        this._currentLayer = new SnippetBufferLayer(buffer, snippetSession)\n\n        const s1 = activeEditor.onCursorMoved.subscribe(() => {\n            if (this.isSnippetActive) {\n                this._activeSession.updateCursorPosition()\n            }\n        })\n\n        const s2 = activeEditor.onModeChanged.subscribe(() => {\n            if (this.isSnippetActive) {\n                this._activeSession.updateCursorPosition()\n            }\n        })\n\n        const s3 = activeEditor.onBufferChanged.subscribe(() => {\n            this._synchronizeSnippetObservable.next()\n        })\n\n        const s4 = snippetSession.onCancel.subscribe(() => {\n            this.cancel()\n        })\n\n        this._disposables = [s1, s2, s3, s4]\n\n        this._activeSession = snippetSession\n    }\n\n    public async nextPlaceholder(): Promise<void> {\n        if (this.isSnippetActive) {\n            return this._activeSession.nextPlaceholder()\n        }\n    }\n\n    public async previousPlaceholder(): Promise<void> {\n        if (this.isSnippetActive) {\n            return this._activeSession.previousPlaceholder()\n        }\n    }\n\n    public async cancel(): Promise<void> {\n        if (this._activeSession) {\n            this._cleanupAfterSession()\n            await (this._editorManager.activeEditor as any).clearSelection()\n\n            // TODO: Add 'stopInsert' and 'startInsert' methods on editor\n            await this._editorManager.activeEditor.neovim.command(\"stopinsert\")\n        }\n\n        if (this._currentLayer) {\n            this._currentLayer.dispose()\n        }\n    }\n\n    private _cleanupAfterSession(): void {\n        Log.info(\"[SnippetManager::cancel]\")\n        this._disposables.forEach(d => d.dispose())\n        this._disposables = []\n        this._activeSession = null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/SnippetProvider.ts",
    "content": "/**\n * SnippetProvider.ts\n *\n * Manages snippet integration\n */\n\nimport * as fs from \"fs\"\nimport * as os from \"os\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { Configuration } from \"./../Configuration\"\n\nimport * as Utility from \"./../../Utility\"\n\nexport class CompositeSnippetProvider implements Oni.Snippets.SnippetProvider {\n    private _providers: Oni.Snippets.SnippetProvider[] = []\n\n    constructor(private _configuration: Configuration) {}\n\n    public registerProvider(provider: Oni.Snippets.SnippetProvider): void {\n        this._providers.push(provider)\n    }\n\n    public async getSnippets(language: string): Promise<Oni.Snippets.Snippet[]> {\n        if (!this._configuration.getValue(\"snippets.enabled\")) {\n            return []\n        }\n\n        const snippets = this._providers.map(p => p.getSnippets(language))\n\n        const allSnippets = await Promise.all(snippets)\n\n        return allSnippets.reduce((prev, cur) => {\n            return [...prev, ...cur]\n        }, [])\n    }\n}\n\nexport interface ISnippetPluginContribution {\n    prefix: string\n    body: string[]\n    description: string\n}\n\nexport class PluginSnippetProvider implements Oni.Snippets.SnippetProvider {\n    private _snippetCache: { [language: string]: Oni.Snippets.Snippet[] } = {}\n\n    constructor(private _pluginManager: PluginManager) {}\n\n    public async getSnippets(language: string): Promise<Oni.Snippets.Snippet[]> {\n        // If we have existing snippets, we'll use those...\n        const currentSnippets = this._snippetCache[language]\n        if (currentSnippets) {\n            return currentSnippets\n        }\n\n        // Otherwise, we need to discover snippets\n\n        const filteredPlugins = this._pluginManager.plugins.filter(\n            p => p.metadata && p.metadata.contributes && p.metadata.contributes.snippets,\n        )\n\n        const snippets = Utility.flatMap(\n            filteredPlugins,\n            pc => pc.metadata.contributes.snippets,\n        ).filter(s => s.language === language)\n\n        const snippetLoadPromises = snippets.map(s => this._loadSnippetsFromFile(s.path))\n        const loadedSnippets = await Promise.all(snippetLoadPromises)\n        const flattenedSnippets = loadedSnippets.reduce(\n            (x: Oni.Snippets.Snippet[], y: Oni.Snippets.Snippet[]) => [...x, ...y],\n            [],\n        )\n\n        this._snippetCache[language] = flattenedSnippets\n        return flattenedSnippets\n    }\n\n    private async _loadSnippetsFromFile(snippetFilePath: string): Promise<Oni.Snippets.Snippet[]> {\n        return loadSnippetsFromFile(snippetFilePath)\n    }\n}\n\nexport const loadSnippetsFromFile = async (\n    snippetFilePath: string,\n): Promise<Oni.Snippets.Snippet[]> => {\n    Log.verbose(\"[loadSnippetsFromFile] Trying to load snippets from: \" + snippetFilePath)\n    const contents = await new Promise<string>((resolve, reject) => {\n        fs.readFile(snippetFilePath, \"utf8\", (err, data) => {\n            if (err) {\n                reject(err)\n                return\n            }\n\n            resolve(data)\n        })\n    })\n\n    const snippets = loadSnippetsFromText(contents)\n\n    Log.verbose(\n        `[loadSnippetsFromFile] - Loaded ${snippets.length} snippets from ${snippetFilePath}`,\n    )\n\n    return snippets\n}\n\ninterface KeyToSnippet {\n    [key: string]: ISnippetPluginContribution\n}\n\nexport const loadSnippetsFromText = (contents: string): Oni.Snippets.Snippet[] => {\n    let snippets: ISnippetPluginContribution[] = []\n    try {\n        const snippetObject = Utility.parseJson5<KeyToSnippet>(contents)\n        snippets = Object.values(snippetObject)\n    } catch (ex) {\n        Log.error(ex)\n        snippets = []\n    }\n\n    const normalizedSnippets = snippets.map(\n        (snip: ISnippetPluginContribution): Oni.Snippets.Snippet => {\n            return {\n                prefix: snip.prefix,\n                description: snip.description,\n                body: typeof snip.body === \"string\" ? snip.body : snip.body.join(os.EOL),\n            }\n        },\n    )\n\n    return normalizedSnippets\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/SnippetSession.ts",
    "content": "/**\n * Snippets.ts\n *\n * Manages snippet integration\n */\n\nimport * as detectIndent from \"detect-indent\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { OniSnippet, OniSnippetPlaceholder } from \"./OniSnippet\"\n\nimport { BufferIndentationInfo, IBuffer } from \"./../../Editor/BufferManager\"\n\nimport { SnippetVariableResolver } from \"./SnippetVariableResolver\"\n\nexport const splitLineAtPosition = (line: string, position: number): [string, string] => {\n    const prefix = line.substring(0, position)\n    const post = line.substring(position, line.length)\n    return [prefix, post]\n}\n\nexport const getFirstPlaceholder = (\n    placeholders: OniSnippetPlaceholder[],\n): OniSnippetPlaceholder => {\n    return placeholders.reduce((prev: OniSnippetPlaceholder, curr: OniSnippetPlaceholder) => {\n        if (!prev || prev.isFinalTabstop) {\n            return curr\n        }\n\n        if (curr.index < prev.index && !curr.isFinalTabstop) {\n            return curr\n        }\n        return prev\n    }, null)\n}\n\nexport const getPlaceholderByIndex = (\n    placeholders: OniSnippetPlaceholder[],\n    index: number,\n): OniSnippetPlaceholder | null => {\n    const matchingPlaceholders = placeholders.filter(p => p.index === index)\n\n    if (matchingPlaceholders.length === 0) {\n        return null\n    }\n\n    return matchingPlaceholders[0]\n}\n\nexport const getFinalPlaceholder = (\n    placeholders: OniSnippetPlaceholder[],\n): OniSnippetPlaceholder | null => {\n    const matchingPlaceholders = placeholders.filter(p => p.isFinalTabstop)\n\n    if (matchingPlaceholders.length === 0) {\n        return null\n    }\n\n    return matchingPlaceholders[0]\n}\n\nexport interface IMirrorCursorUpdateEvent {\n    mode: Oni.Vim.Mode\n    cursors: types.Range[]\n}\n\nexport const makeSnippetConsistentWithExistingWhitespace = (\n    snippet: string,\n    info: BufferIndentationInfo,\n) => {\n    return snippet.split(\"\\t\").join(info.indent)\n}\n\nexport const makeSnippetIndentationConsistent = (snippet: string, info: BufferIndentationInfo) => {\n    return snippet\n        .split(\"\\n\")\n        .map((line, index) => {\n            if (index === 0) {\n                return line\n            } else {\n                return info.indent + line\n            }\n        })\n        .join(\"\\n\")\n}\n\nexport class SnippetSession {\n    private _buffer: IBuffer\n    private _snippet: OniSnippet\n    private _position: types.Position\n    private _onCancelEvent: Event<void> = new Event<void>()\n    private _onCursorMovedEvent: Event<IMirrorCursorUpdateEvent> = new Event<\n        IMirrorCursorUpdateEvent\n    >()\n\n    // Get state of line where we inserted\n    private _prefix: string\n    private _suffix: string\n\n    private _currentPlaceholder: OniSnippetPlaceholder = null\n\n    private _lastCursorMovedEvent: IMirrorCursorUpdateEvent = {\n        mode: null,\n        cursors: [],\n    }\n\n    public get buffer(): IBuffer {\n        return this._buffer\n    }\n\n    public get onCancel(): IEvent<void> {\n        return this._onCancelEvent\n    }\n\n    public get onCursorMoved(): IEvent<IMirrorCursorUpdateEvent> {\n        return this._onCursorMovedEvent\n    }\n\n    public get position(): types.Position {\n        return this._position\n    }\n\n    public get lines(): string[] {\n        return this._snippet.getLines()\n    }\n\n    constructor(private _editor: Oni.Editor, private _snippetString: string) {}\n\n    public async start(): Promise<void> {\n        this._buffer = this._editor.activeBuffer as IBuffer\n\n        const cursorPosition = await this._buffer.getCursorPosition()\n        const [currentLine] = await this._buffer.getLines(\n            cursorPosition.line,\n            cursorPosition.line + 1,\n        )\n\n        this._position = cursorPosition\n\n        const [prefix, suffix] = splitLineAtPosition(currentLine, cursorPosition.character)\n        const currentIndent = detectIndent(currentLine)\n\n        this._prefix = prefix\n        this._suffix = suffix\n\n        const whitespaceSettings = await this._buffer.detectIndentation()\n        const normalizedSnippet = makeSnippetConsistentWithExistingWhitespace(\n            this._snippetString,\n            whitespaceSettings,\n        )\n        const indentedSnippet = makeSnippetIndentationConsistent(normalizedSnippet, currentIndent)\n        this._snippet = new OniSnippet(indentedSnippet, new SnippetVariableResolver(this._buffer))\n\n        const snippetLines = this._snippet.getLines()\n        const lastIndex = snippetLines.length - 1\n        snippetLines[0] = this._prefix + snippetLines[0]\n        snippetLines[lastIndex] = snippetLines[lastIndex] + this._suffix\n\n        // If there are no placeholders, add an implicit one at the end\n        if (this._snippet.getPlaceholders().length === 0) {\n            this._snippet = new OniSnippet(\n                // tslint:disable-next-line\n                indentedSnippet + \"${0}\",\n                new SnippetVariableResolver(this._buffer),\n            )\n        }\n\n        await this._buffer.setLines(cursorPosition.line, cursorPosition.line + 1, snippetLines)\n\n        const placeholders = this._snippet.getPlaceholders()\n\n        if (!placeholders || placeholders.length === 0) {\n            // If no placeholders, we're done with the session\n            this._finish()\n            return\n        }\n\n        await this.nextPlaceholder()\n        await this.updateCursorPosition()\n    }\n\n    public async nextPlaceholder(): Promise<void> {\n        const placeholders = this._snippet.getPlaceholders()\n\n        if (!this._currentPlaceholder) {\n            const newPlaceholder = getFirstPlaceholder(placeholders)\n            this._currentPlaceholder = newPlaceholder\n        } else {\n            if (this._currentPlaceholder.isFinalTabstop) {\n                this._finish()\n                return\n            }\n\n            const nextPlaceholder = getPlaceholderByIndex(\n                placeholders,\n                this._currentPlaceholder.index + 1,\n            )\n            this._currentPlaceholder = nextPlaceholder || getFinalPlaceholder(placeholders)\n        }\n\n        await this._highlightPlaceholder(this._currentPlaceholder)\n    }\n\n    public async previousPlaceholder(): Promise<void> {\n        const placeholders = this._snippet.getPlaceholders()\n\n        const nextPlaceholder = getPlaceholderByIndex(\n            placeholders,\n            this._currentPlaceholder.index - 1,\n        )\n        this._currentPlaceholder = nextPlaceholder || getFirstPlaceholder(placeholders)\n\n        await this._highlightPlaceholder(this._currentPlaceholder)\n    }\n\n    public async setPlaceholderValue(index: number, val: string): Promise<void> {\n        const previousValue = this._snippet.getPlaceholderValue(index)\n\n        if (previousValue === val) {\n            Log.verbose(\n                \"[SnippetSession::setPlaceHolderValue] Skipping because new placeholder value is same as previous\",\n            )\n            return\n        }\n\n        await this._snippet.setPlaceholder(index, val)\n        // Update current placeholder\n        this._currentPlaceholder = getPlaceholderByIndex(this._snippet.getPlaceholders(), index)\n        await this._updateSnippet()\n    }\n\n    // Update the cursor position relative to all placeholders\n    public async updateCursorPosition(): Promise<void> {\n        const pos = await this._buffer.getCursorPosition()\n\n        const mode = this._editor.mode as Oni.Vim.Mode\n\n        if (\n            !this._currentPlaceholder ||\n            pos.line !== this._currentPlaceholder.line + this._position.line\n        ) {\n            return\n        }\n\n        const boundsForPlaceholder = this._getBoundsForPlaceholder()\n\n        const offset = pos.character - boundsForPlaceholder.start\n\n        const allPlaceholdersAtIndex = this._snippet\n            .getPlaceholders()\n            .filter(\n                f =>\n                    f.index === this._currentPlaceholder.index &&\n                    !(\n                        f.line === this._currentPlaceholder.line &&\n                        f.character === this._currentPlaceholder.character\n                    ),\n            )\n\n        const cursorPositions: types.Range[] = allPlaceholdersAtIndex.map(p => {\n            if (mode === \"visual\") {\n                const bounds = this._getBoundsForPlaceholder(p)\n                return types.Range.create(\n                    bounds.line,\n                    bounds.start,\n                    bounds.line,\n                    bounds.start + bounds.length,\n                )\n            } else {\n                const bounds = this._getBoundsForPlaceholder(p)\n                return types.Range.create(\n                    bounds.line,\n                    bounds.start + offset,\n                    bounds.line,\n                    bounds.start + offset,\n                )\n            }\n        })\n\n        this._lastCursorMovedEvent = {\n            mode,\n            cursors: cursorPositions,\n        }\n\n        this._onCursorMovedEvent.dispatch(this._lastCursorMovedEvent)\n    }\n\n    public getLatestCursors(): IMirrorCursorUpdateEvent {\n        return this._lastCursorMovedEvent\n    }\n\n    // Helper method to query the value of the current placeholder,\n    // propagate that to any other placeholders, and update the snippet\n    public async synchronizeUpdatedPlaceholders(): Promise<void> {\n        // Get current cursor position\n        const cursorPosition = await this._buffer.getCursorPosition()\n\n        if (!this._currentPlaceholder) {\n            return\n        }\n\n        const bounds = this._getBoundsForPlaceholder()\n\n        if (cursorPosition.line !== bounds.line) {\n            Log.info(\n                \"[SnippetSession::synchronizeUpdatedPlaceholder] Cursor outside snippet, cancelling snippet session\",\n            )\n            this._onCancelEvent.dispatch()\n            return\n        }\n\n        // Check substring of placeholder start / placeholder finish\n        const [currentLine] = await this._buffer.getLines(bounds.line, bounds.line + 1)\n\n        const startPosition = bounds.start\n        const endPosition = currentLine.length - bounds.distanceFromEnd\n\n        if (\n            cursorPosition.character < startPosition ||\n            cursorPosition.character > endPosition + 2\n        ) {\n            return\n        }\n\n        // Set placeholder value\n        const newPlaceholderValue = currentLine.substring(startPosition, endPosition)\n        await this.setPlaceholderValue(bounds.index, newPlaceholderValue)\n    }\n\n    private _finish(): void {\n        this._onCancelEvent.dispatch()\n    }\n\n    private _getBoundsForPlaceholder(\n        currentPlaceholder: OniSnippetPlaceholder = this._currentPlaceholder,\n    ): {\n        index: number\n        line: number\n        start: number\n        length: number\n        distanceFromEnd: number\n    } {\n        const currentSnippetLines = this._snippet.getLines()\n\n        const start =\n            currentPlaceholder.line === 0\n                ? this._prefix.length + currentPlaceholder.character\n                : currentPlaceholder.character\n        const length = currentPlaceholder.value.length\n        const distanceFromEnd =\n            currentSnippetLines[currentPlaceholder.line].length -\n            (currentPlaceholder.character + length)\n        const line = currentPlaceholder.line + this._position.line\n\n        return { index: currentPlaceholder.index, line, start, length, distanceFromEnd }\n    }\n\n    private async _updateSnippet(): Promise<void> {\n        const snippetLines = this._snippet.getLines()\n        const lastIndex = snippetLines.length - 1\n        snippetLines[0] = this._prefix + snippetLines[0]\n        snippetLines[lastIndex] = snippetLines[lastIndex] + this._suffix\n\n        await this._buffer.setLines(\n            this._position.line,\n            this._position.line + snippetLines.length,\n            snippetLines,\n        )\n    }\n\n    private async _highlightPlaceholder(currentPlaceholder: OniSnippetPlaceholder): Promise<void> {\n        if (!currentPlaceholder) {\n            return\n        }\n\n        const adjustedLine = currentPlaceholder.line + this._position.line\n        const adjustedCharacter =\n            currentPlaceholder.line === 0\n                ? this._position.character + currentPlaceholder.character\n                : currentPlaceholder.character\n        const placeHolderLength = currentPlaceholder.value.length\n\n        if (placeHolderLength === 0) {\n            await (this._editor as any).clearSelection()\n            await this._editor.activeBuffer.setCursorPosition(adjustedLine, adjustedCharacter)\n        } else {\n            await this._editor.setSelection(\n                types.Range.create(\n                    adjustedLine,\n                    adjustedCharacter,\n                    adjustedLine,\n                    adjustedCharacter + placeHolderLength - 1,\n                ),\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/SnippetVariableResolver.ts",
    "content": "/**\n * Snippets.ts\n *\n * Manages snippet integration\n */\n\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { Variable, VariableResolver } from \"./OniSnippet\"\n\nexport class SnippetVariableResolver implements VariableResolver {\n    private _variableToValue: { [key: string]: string } = {}\n\n    constructor(private _buffer: Oni.Buffer) {\n        const currentDate = new Date()\n\n        const line = this._buffer && this._buffer.cursor ? this._buffer.cursor.line : 0\n        const filePath = this._buffer && this._buffer.filePath ? this._buffer.filePath : \"\"\n\n        this._variableToValue = {\n            CURRENT_YEAR: currentDate.getFullYear().toString(),\n            CURRENT_YEAR_SHORT: currentDate\n                .getFullYear()\n                .toString()\n                .slice(-2),\n            CURRENT_MONTH: (currentDate.getMonth() + 1).toString(),\n            CURRENT_DATE: currentDate.getDate().toString(),\n            CURRENT_HOUR: currentDate.getHours().toString(),\n            CURRENT_MINUTE: currentDate.getMinutes().toString(),\n            CURRENT_SECOND: currentDate.getSeconds().toString(),\n            CURRENT_DAY_NAME: currentDate.toLocaleString(\"en-US\", { weekday: \"long\" }),\n            CURRENT_DAY_NAME_SHORT: currentDate.toLocaleString(\"en-US\", { weekday: \"short\" }),\n            CURRENT_MONTH_NAME: currentDate.toLocaleString(\"en-US\", { month: \"long\" }),\n            CURRENT_MONTH_NAME_SHORT: currentDate.toLocaleString(\"en-US\", { month: \"short\" }),\n            // SELECTION: \"\",\n            // CLIPBOARD: \"\",\n            // TM_SELECTED_TEXT: \"\",\n            // TM_CURRENT_LINE: \"\",\n            // TM_CURRENT_WORD: \"\",\n            TM_LINE_INDEX: line.toString(),\n            TM_LINE_NUMBER: (line + 1).toString(),\n            TM_FILENAME: path.basename(filePath),\n            TM_FILENAME_BASE: path.basename(filePath, path.extname(filePath)),\n            TM_DIRECTORY: path.dirname(filePath),\n            TM_FILEPATH: filePath,\n        }\n    }\n\n    public resolve(variable: Variable): string {\n        const variableName = variable.name\n        if (!this._variableToValue[variableName]) {\n            return \"\"\n        }\n\n        return this._variableToValue[variableName]\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/UserSnippetProvider.ts",
    "content": "/**\n * UserSnippetProvider.ts\n *\n * Manages loading user snippets, and opening user snippet files\n */\n\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { loadSnippetsFromFile } from \"./SnippetProvider\"\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { Configuration, getUserConfigFolderPath } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\n\nconst GLOBAL_SNIPPET_NAME = \"global_snippets\"\n\nconst SnippetTemplate = [\n    \"{\",\n    '   \"For_Loop\": {',\n    '       \"prefix\": \"for\",',\n    '       \"body\": [',\n    '         \"for (const ${2:element} of ${1:array}) {\",', // tslint:disable-line\n    '         \"\\\\t$0\",', //tslint:disable-line\n    '         \"}\"',\n    \"       ],\",\n    '       \"description\": \"For Loop\"',\n    \"   }\",\n    \"}\",\n]\n\nexport class UserSnippetProvider implements Oni.Snippets.SnippetProvider {\n    private _snippetCache: { [language: string]: Oni.Snippets.Snippet[] } = {}\n    private _isWatching: boolean = false\n\n    private _fileTypesToEditSnippets: Set<string> = new Set<string>()\n\n    constructor(\n        private _commandManager: CommandManager,\n        private _configuration: Configuration,\n        private _editorManager: EditorManager,\n    ) {\n        this._startWatchingSnippetsFolderIfExists()\n\n        this._editorManager.anyEditor.onBufferEnter.subscribe(bufEnter => {\n            this._addCommandForLanguage(bufEnter.language)\n        })\n\n        this._commandManager.registerCommand({\n            command: \"userSnippets.editGlobal\",\n            name: \"Snippets: Edit User Snippets (global)\",\n            detail: \"Edit user snippet definitions for all files.\",\n            execute: () => this._editSnippetFile(GLOBAL_SNIPPET_NAME),\n        })\n    }\n\n    public async getSnippets(language: string): Promise<Oni.Snippets.Snippet[]> {\n        const globalSnippets = await this._getSnippetForLanguage(GLOBAL_SNIPPET_NAME)\n        const languageSnippets = await this._getSnippetForLanguage(language)\n\n        return [...globalSnippets, ...languageSnippets]\n    }\n\n    public getUserSnippetFilePath(language: string): string {\n        const snippetPath = this._getSnippetFolder()\n        return path.join(snippetPath, language + \".json\")\n    }\n\n    private _addCommandForLanguage(language: string): void {\n        if (!this._fileTypesToEditSnippets.has(language)) {\n            this._commandManager.registerCommand({\n                command: `userSnippets.edit.${language}`,\n                name: `Snippets: Edit User Snippets (${language})`,\n                detail: `Edit user snippet definitions for ${language} files.`,\n                execute: () => this._editSnippetFile(language),\n                enabled: () => this._editorManager.activeEditor.activeBuffer.language === language,\n            })\n\n            this._fileTypesToEditSnippets.add(language)\n        }\n    }\n\n    private async _editSnippetFile(language: string): Promise<void> {\n        // Make sure snippet folder exists\n        const snippetFilePath = this.getUserSnippetFilePath(language)\n        const snippetFolder = path.dirname(snippetFilePath)\n\n        mkdirp.sync(snippetFolder)\n        this._startWatchingSnippetsFolderIfExists()\n\n        const isNewFile = !fs.existsSync(snippetFilePath)\n\n        const buf = await this._editorManager.activeEditor.openFile(snippetFilePath, {\n            openMode: Oni.FileOpenMode.VerticalSplit,\n        })\n\n        if (isNewFile) {\n            await buf.setLines(0, 1, SnippetTemplate)\n        }\n    }\n\n    private _startWatchingSnippetsFolderIfExists(): void {\n        if (this._isWatching) {\n            return\n        }\n\n        if (!fs.existsSync(this._getSnippetFolder())) {\n            return\n        }\n\n        Log.info(\"UserSnippetProvider - installing watcher...\")\n\n        this._isWatching = true\n\n        fs.watch(this._getSnippetFolder(), (evt, filename) => {\n            Log.info(\"UserSnippetProvider - invalidating cache because a change was detected.\")\n            this._snippetCache = {}\n        })\n    }\n\n    private _getSnippetFolder(): string {\n        return (\n            this._configuration.getValue(\"snippets.userSnippetFolder\") ||\n            path.join(getUserConfigFolderPath(), \"snippets\")\n        )\n    }\n\n    private async _getSnippetForLanguage(language: string): Promise<Oni.Snippets.Snippet[]> {\n        if (this._snippetCache[language]) {\n            return this._snippetCache[language]\n        }\n\n        const filePath = this.getUserSnippetFilePath(language)\n\n        let snippets: Oni.Snippets.Snippet[] = []\n        if (fs.existsSync(filePath)) {\n            snippets = await loadSnippetsFromFile(filePath)\n        }\n\n        this._snippetCache[language] = snippets\n        return snippets\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Snippets/index.ts",
    "content": "export * from \"./OniSnippet\"\nexport * from \"./SnippetManager\"\nexport * from \"./SnippetSession\"\nexport * from \"./SnippetVariableResolver\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { CommandManager } from \"./../CommandManager\"\nimport { CompletionProviders } from \"./../Completion\"\nimport { Configuration } from \"./../Configuration\"\nimport { editorManager } from \"./../EditorManager\"\n\nimport { SnippetCompletionProvider } from \"./SnippetCompletionProvider\"\nimport { SnippetManager } from \"./SnippetManager\"\n\nimport { PluginSnippetProvider } from \"./SnippetProvider\"\nimport { UserSnippetProvider } from \"./UserSnippetProvider\"\n\nlet _snippetManager: SnippetManager\n\nexport const activate = (commandManager: CommandManager, configuration: Configuration) => {\n    _snippetManager = new SnippetManager(configuration, editorManager)\n\n    commandManager.registerCommand({\n        command: \"snippet.nextPlaceholder\",\n        name: null,\n        detail: null,\n        enabled: () => _snippetManager.isSnippetActive,\n        execute: () => _snippetManager.nextPlaceholder(),\n    })\n\n    commandManager.registerCommand({\n        command: \"snippet.previousPlaceholder\",\n        name: null,\n        detail: null,\n        enabled: () => _snippetManager.isSnippetActive,\n        execute: () => _snippetManager.previousPlaceholder(),\n    })\n\n    commandManager.registerCommand({\n        command: \"snippet.cancel\",\n        name: null,\n        detail: null,\n        enabled: () => _snippetManager.isSnippetActive,\n        execute: () => _snippetManager.cancel(),\n    })\n}\n\nexport const activateProviders = (\n    commandManager: CommandManager,\n    completionProviders: CompletionProviders,\n    configuration: Configuration,\n    pluginManager: PluginManager,\n) => {\n    completionProviders.registerCompletionProvider(\n        \"oni-snippets\",\n        new SnippetCompletionProvider(_snippetManager),\n    )\n\n    _snippetManager.registerSnippetProvider(new PluginSnippetProvider(pluginManager))\n    const userProvider = new UserSnippetProvider(commandManager, configuration, editorManager)\n    _snippetManager.registerSnippetProvider(userProvider)\n}\n\nexport const getInstance = (): SnippetManager => {\n    return _snippetManager\n}\n"
  },
  {
    "path": "browser/src/Services/StatusBar.ts",
    "content": "/**\n * StatusBar.ts\n *\n * Implements API surface area for working with the status bar\n */\n\nimport { Subject } from \"rxjs/Subject\"\nimport { Subscription } from \"rxjs/Subscription\"\n\nimport \"rxjs/add/operator/auditTime\"\nimport \"rxjs/add/operator/debounceTime\"\n\nimport * as Oni from \"oni-api\"\nimport { Configuration } from \"./Configuration\"\n\nimport * as Shell from \"./../UI/Shell\"\n\nexport enum StatusBarAlignment {\n    Left,\n    Right,\n}\n\nexport class StatusBarItem implements Oni.StatusBarItem {\n    private _contents: JSX.Element\n    private _visible: boolean = false\n\n    private _setContentsSubject: Subject<any> = new Subject<any>()\n    private _subscription: Subscription\n\n    constructor(\n        private _id: string,\n        private _alignment?: StatusBarAlignment | null,\n        private _priority?: number | null,\n    ) {\n        this._subscription = this._setContentsSubject\n            .debounceTime(25)\n            .subscribe((contents: any) => {\n                if (this._visible) {\n                    this.show()\n                }\n            })\n    }\n\n    public show(): void {\n        this._visible = true\n        Shell.Actions.showStatusBarItem(this._id, this._contents, this._alignment, this._priority)\n    }\n\n    public hide(): void {\n        this._visible = false\n        Shell.Actions.hideStatusBarItem(this._id)\n    }\n\n    public setContents(element: any): void {\n        this._contents = element\n        this._setContentsSubject.next(element)\n    }\n\n    public dispose(): void {\n        if (this._subscription) {\n            this._subscription.unsubscribe()\n            this._subscription = null\n            this._setContentsSubject = null\n        }\n    }\n}\n\nclass StatusBar implements Oni.StatusBar {\n    private _id: number = 0\n\n    constructor(private _configuration: Configuration) {}\n\n    public getItem(globalId: string): Oni.StatusBarItem {\n        return new StatusBarItem(globalId)\n    }\n\n    public createItem(alignment: StatusBarAlignment, globalId?: string): Oni.StatusBarItem {\n        this._id++\n        const statusBarId = globalId || `${this._id}`\n        const statusItems = this._configuration.getValue(\"statusbar.priority\")\n        const currentItem = statusItems[globalId]\n        const itemPriority = currentItem || 0\n\n        return new StatusBarItem(statusBarId, alignment, itemPriority)\n    }\n}\n\nlet _statusBar: StatusBar = null\nexport const activate = (configuration: Configuration): void => {\n    _statusBar = new StatusBar(configuration)\n}\n\nexport const getInstance = (): StatusBar => {\n    return _statusBar\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/Definitions.ts",
    "content": "import * as types from \"vscode-languageserver-types\"\n\nimport { TokenColor } from \"./../TokenColors\"\n\nexport interface HighlightInfo {\n    range: types.Range\n    tokenColor: TokenColor\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/GrammarLoader.ts",
    "content": "import { IGrammar, Registry } from \"vscode-textmate\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { configuration } from \"./../Configuration\"\n\nexport interface IGrammarLoader {\n    getGrammarForLanguage(language: string, extension: string): Promise<IGrammar>\n}\n\nexport interface ExtensionToGrammarMap {\n    [extension: string]: string\n}\n\nexport const getPathForLanguage = (language: string, extension: string): string => {\n    const verifiedLanguage = language.includes(\".\") ? language.split(\".\")[0] : language\n    const grammar: string | ExtensionToGrammarMap = configuration.getValue(\n        \"language.\" + verifiedLanguage + \".textMateGrammar\",\n    )\n\n    if (!grammar) {\n        Log.warn(\"No grammar found for language: \" + language)\n        return null\n    } else if (typeof grammar === \"string\") {\n        return grammar\n    } else {\n        return grammar[extension] || null\n    }\n}\n\nexport class GrammarLoader implements IGrammarLoader {\n    private _grammarCache: { [language: string]: IGrammar } = {}\n\n    constructor(private _registry: Registry = new Registry()) {}\n\n    public async getGrammarForLanguage(language: string, extension: string): Promise<IGrammar> {\n        if (!language) {\n            return null\n        }\n\n        if (language in this._grammarCache) {\n            return this._grammarCache[language]\n        }\n\n        const filePath = getPathForLanguage(language, extension)\n\n        if (!filePath) {\n            return null\n        }\n\n        const grammar = this._registry.loadGrammarFromPathSync(filePath)\n\n        this._grammarCache[language] = grammar\n\n        return grammar\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/ISyntaxHighlighter.ts",
    "content": "/**\n * ISyntaxHighlighter.ts\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport { IDisposable } from \"oni-types\"\n\nimport { ISyntaxHighlightTokenInfo } from \"./SyntaxHighlightingStore\"\n\nexport interface ISyntaxHighlighter extends IDisposable {\n    notifyBufferUpdate(evt: Oni.EditorBufferChangedEventArgs): Promise<void>\n    notifyViewportChanged(bufferId: string, topLineInView: number, bottomLineInView: number): void\n    notifyColorschemeRedraw(id: string): void\n\n    getHighlightTokenAt(bufferId: string, position: types.Position): ISyntaxHighlightTokenInfo\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/SyntaxHighlightReconciler.ts",
    "content": "/**\n * SyntaxHighlighting.ts\n *\n * Handles enhanced syntax highlighting\n */\n\nimport { Buffer, Editor } from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { prettyPrint } from \"./../../Utility\"\nimport { TokenColor, TokenColors } from \"./../TokenColors\"\n\nimport { HighlightInfo } from \"./Definitions\"\nimport {\n    ISyntaxHighlightLineInfo,\n    ISyntaxHighlightState,\n    ISyntaxHighlightTokenInfo,\n} from \"./SyntaxHighlightingStore\"\nimport { TokenScorer } from \"./TokenScorer\"\n\nimport { IBufferHighlightsUpdater } from \"../../Editor/BufferHighlights\"\nimport * as Selectors from \"./SyntaxHighlightSelectors\"\n\ninterface IBufferWithSyntaxHighlighter extends Buffer {\n    updateHighlights?: (\n        tokenColors: TokenColor[],\n        highlightCallback: (args: IBufferHighlightsUpdater) => void,\n    ) => void\n}\n\nexport interface IEditorWithSyntaxHighlighter extends Editor {\n    activeBuffer: IBufferWithSyntaxHighlighter\n}\n\n/**\n * SyntaxHighlightReconciler\n *\n * Essentially a renderer / reconciler, that will push\n * highlight calls to the active buffer based on the active\n * window and viewport\n * @name SyntaxHighlightReconciler\n * @class\n */\nexport class SyntaxHighlightReconciler {\n    private _previousState: { [line: number]: ISyntaxHighlightLineInfo } = {}\n    private _tokenScorer = new TokenScorer()\n\n    constructor(private _editor: IEditorWithSyntaxHighlighter, private _tokenColors: TokenColors) {}\n\n    public update(state: ISyntaxHighlightState) {\n        const { activeBuffer } = this._editor\n\n        if (!activeBuffer) {\n            return\n        }\n\n        const bufferId = activeBuffer.id\n\n        const currentHighlightState = state.bufferToHighlights[bufferId]\n\n        if (currentHighlightState && currentHighlightState.lines) {\n            const lineNumbers = Object.keys(currentHighlightState.lines)\n\n            const relevantRange = Selectors.getRelevantRange(state, bufferId)\n\n            const filteredLines = lineNumbers.filter(line => {\n                const lineNumber = parseInt(line, 10)\n\n                // Ignore lines that are not in current view\n                if (lineNumber < relevantRange.top || lineNumber > relevantRange.bottom) {\n                    return false\n                }\n\n                const latestLine = Selectors.getLineFromBuffer(currentHighlightState, lineNumber)\n\n                // If dirty (haven't processed tokens yet) - skip\n                if (latestLine.dirty) {\n                    return false\n                }\n\n                // Or lines that haven't been updated\n                return this._previousState[line] !== latestLine\n            })\n\n            const tokens = filteredLines.map(currentLine => {\n                const lineNumber = parseInt(currentLine, 10)\n                const line = Selectors.getLineFromBuffer(currentHighlightState, lineNumber)\n\n                const highlights = this._mapTokensToHighlights(line.tokens)\n                return {\n                    line: parseInt(currentLine, 10),\n                    highlights,\n                }\n            })\n\n            // Get only the token colors that apply to the visible section of the buffer\n            const visibleTokens = tokens.reduce((accumulator, { highlights }) => {\n                if (highlights) {\n                    const tokenColors = highlights.map(({ tokenColor }) => tokenColor)\n                    accumulator.push(...tokenColors)\n                }\n                return accumulator\n            }, [])\n\n            filteredLines.forEach(line => {\n                const lineNumber = parseInt(line, 10)\n                this._previousState[line] = Selectors.getLineFromBuffer(\n                    currentHighlightState,\n                    lineNumber,\n                )\n            })\n\n            if (tokens.length) {\n                Log.verbose(\n                    `[SyntaxHighlightReconciler] Applying changes to ${tokens.length} lines.`,\n                )\n                activeBuffer.updateHighlights(visibleTokens, highlightUpdater => {\n                    tokens.forEach(token => {\n                        const { line, highlights } = token\n                        if (Log.isDebugLoggingEnabled()) {\n                            Log.debug(\n                                `[SyntaxHighlightingReconciler] Updating tokens for line: ${line} | ${prettyPrint(\n                                    highlights,\n                                )}`,\n                            )\n                        }\n\n                        highlightUpdater.setHighlightsForLine(line, highlights)\n                    })\n                })\n            }\n        }\n    }\n\n    private _mapTokensToHighlights(tokens: ISyntaxHighlightTokenInfo[]): HighlightInfo[] {\n        const mapTokenToHighlight = (token: ISyntaxHighlightTokenInfo) => ({\n            tokenColor: this._getHighlightGroupFromScope(token.scopes),\n            range: token.range,\n        })\n\n        return tokens.map(mapTokenToHighlight).filter(t => !!t.tokenColor)\n    }\n\n    private _getHighlightGroupFromScope(scopes: string[]): TokenColor {\n        const highestRanked = this._tokenScorer.rankTokenScopes(\n            scopes,\n            this._tokenColors.tokenColors,\n        )\n        return highestRanked\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/SyntaxHighlightSelectors.ts",
    "content": "// SyntaxHighlightingSelectors.ts\n//\n// Reducers for handling state changes from ISyntaxHighlightActions\n\nimport {\n    IBufferSyntaxHighlightState,\n    ISyntaxHighlightLineInfo,\n    ISyntaxHighlightState,\n} from \"./SyntaxHighlightingStore\"\n\nexport interface SyntaxHighlightRange {\n    top: number\n    bottom: number\n}\n\nexport const NullRange: SyntaxHighlightRange = { top: -1, bottom: -1 }\n\nexport const getRelevantRange = (\n    state: ISyntaxHighlightState,\n    bufferId: number | string,\n): SyntaxHighlightRange => {\n    if (!state.bufferToHighlights[bufferId]) {\n        return NullRange\n    }\n\n    const buffer = state.bufferToHighlights[bufferId]\n\n    return {\n        top: buffer.topVisibleLine,\n        bottom: buffer.bottomVisibleLine,\n    }\n}\n\nexport const getLineFromBuffer = (\n    state: IBufferSyntaxHighlightState,\n    lineNumber: number,\n): ISyntaxHighlightLineInfo => {\n    const currentLine = state.lines[lineNumber]\n\n    if (\n        state.insertModeLine &&\n        state.insertModeLine.info &&\n        state.insertModeLine.version > currentLine.version &&\n        state.insertModeLine.lineNumber === lineNumber\n    ) {\n        return state.insertModeLine.info\n    }\n\n    return currentLine\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/SyntaxHighlighting.ts",
    "content": "/**\n * SyntaxHighlighting.ts\n *\n * Handles enhanced syntax highlighting\n */\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport { Subject } from \"rxjs/Subject\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { Store, Unsubscribe } from \"redux\"\n\nimport { TokenColors } from \"./../TokenColors\"\n\nimport { NeovimEditor } from \"./../../Editor/NeovimEditor\"\n\nimport {\n    createSyntaxHighlightStore,\n    ISyntaxHighlightAction,\n    ISyntaxHighlightState,\n    ISyntaxHighlightTokenInfo,\n} from \"./SyntaxHighlightingStore\"\n\nimport { ISyntaxHighlighter } from \"./ISyntaxHighlighter\"\nimport {\n    IEditorWithSyntaxHighlighter,\n    SyntaxHighlightReconciler,\n} from \"./SyntaxHighlightReconciler\"\nimport { getLineFromBuffer } from \"./SyntaxHighlightSelectors\"\n\nimport * as Utility from \"./../../Utility\"\n\nexport class SyntaxHighlighter implements ISyntaxHighlighter {\n    private _store: Store<ISyntaxHighlightState>\n    private _reconciler: SyntaxHighlightReconciler\n    private _unsubscribe: Unsubscribe\n\n    private _throttledActions: Subject<ISyntaxHighlightAction> = new Subject<\n        ISyntaxHighlightAction\n    >()\n\n    constructor(private _editor: NeovimEditor, private _tokenColors: TokenColors) {\n        this._store = createSyntaxHighlightStore()\n\n        this._reconciler = new SyntaxHighlightReconciler(\n            this._editor as IEditorWithSyntaxHighlighter,\n            this._tokenColors,\n        )\n        this._unsubscribe = this._store.subscribe(() => {\n            const state = this._store.getState()\n            this._reconciler.update(state)\n        })\n\n        this._throttledActions.auditTime(50).subscribe(action => {\n            this._store.dispatch(action)\n        })\n    }\n\n    public notifyViewportChanged(\n        bufferId: string,\n        topLineInView: number,\n        bottomLineInView: number,\n    ): void {\n        Log.verbose(\n            `[SyntaxHighlighting.notifyViewportChanged] -\n             bufferId: ${bufferId} \n             topLineInView: ${topLineInView}\n             bottomLineInView:  ${bottomLineInView}`,\n        )\n\n        const state = this._store.getState()\n        const previousBufferState = state.bufferToHighlights[bufferId]\n\n        if (\n            previousBufferState &&\n            topLineInView === previousBufferState.topVisibleLine &&\n            bottomLineInView === previousBufferState.bottomVisibleLine\n        ) {\n            return\n        }\n\n        this._store.dispatch({\n            type: \"SYNTAX_UPDATE_BUFFER_VIEWPORT\",\n            bufferId,\n            topVisibleLine: topLineInView,\n            bottomVisibleLine: bottomLineInView,\n        })\n    }\n\n    public async notifyColorschemeRedraw(bufferId: string) {\n        this._store.dispatch({ type: \"SYNTAX_RESET_BUFFER\", bufferId })\n    }\n\n    public async notifyBufferUpdate(evt: Oni.EditorBufferChangedEventArgs): Promise<void> {\n        const firstChange = evt.contentChanges[0]\n        if (!firstChange.range && !firstChange.rangeLength) {\n            const lines = firstChange.text.split(os.EOL)\n            this._store.dispatch({\n                type: \"SYNTAX_UPDATE_BUFFER\",\n                extension: path.extname(evt.buffer.filePath),\n                language: evt.buffer.language,\n                bufferId: evt.buffer.id,\n                lines,\n                version: evt.buffer.version,\n            })\n        } else {\n            // Incremental update\n            this._throttledActions.next({\n                type: \"SYNTAX_UPDATE_BUFFER_LINE\",\n                bufferId: evt.buffer.id,\n                version: evt.buffer.version,\n                lineNumber: firstChange.range.start.line,\n                line: firstChange.text,\n            })\n        }\n    }\n\n    public getHighlightTokenAt(\n        bufferId: string,\n        position: types.Position,\n    ): ISyntaxHighlightTokenInfo {\n        const state = this._store.getState()\n        const buffer = state.bufferToHighlights[bufferId]\n\n        if (!buffer) {\n            return null\n        }\n\n        const line = getLineFromBuffer(buffer, position.line)\n\n        if (!line) {\n            return null\n        }\n\n        return line.tokens.find(r => Utility.isInRange(position.line, position.character, r.range))\n    }\n\n    public dispose(): void {\n        if (this._reconciler) {\n            this._reconciler = null\n        }\n\n        if (this._unsubscribe) {\n            this._unsubscribe()\n            this._unsubscribe = null\n        }\n    }\n}\n\nexport class NullSyntaxHighlighter implements ISyntaxHighlighter {\n    public notifyBufferUpdate(evt: Oni.EditorBufferChangedEventArgs): Promise<void> {\n        return Promise.resolve(null)\n    }\n\n    public getHighlightTokenAt(\n        bufferId: string,\n        position: types.Position,\n    ): ISyntaxHighlightTokenInfo {\n        return null\n    }\n\n    public notifyColorschemeRedraw(id: string): void {\n        return null\n    }\n\n    public notifyViewportChanged(\n        bufferId: string,\n        topLineInView: number,\n        bottomLineInView: number,\n    ): void {\n        // tslint: disable-line\n    }\n\n    public dispose(): void {} // tslint:disable-line\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/SyntaxHighlightingPeriodicJob.ts",
    "content": "/**\n * SyntaxHighlightingPeridiocJob.ts\n *\n * Periodic (asynchronous) job to process syntax highlights\n */\n\nimport { Store } from \"redux\"\n\nimport * as types from \"vscode-languageserver-types\"\nimport { IGrammar } from \"vscode-textmate\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as SyntaxHighlighting from \"./SyntaxHighlightingStore\"\nimport * as Selectors from \"./SyntaxHighlightSelectors\"\n\nimport { IPeriodicJob } from \"./../../PeriodicJobs\"\n\nexport const SYNTAX_JOB_BUDGET = 10 // Budget in milliseconds - time to allow the job to run for\n\nexport class SyntaxHighlightingPeriodicJob implements IPeriodicJob {\n    constructor(\n        private _store: Store<SyntaxHighlighting.ISyntaxHighlightState>,\n        private _bufferId: string,\n        private _grammar: IGrammar,\n        private _topLine: number,\n        private _bottomLine: number,\n    ) {}\n\n    public execute(): boolean {\n        const start = new Date().getTime()\n\n        // If the window has changed, we should bail\n        const currentWindow = Selectors.getRelevantRange(this._store.getState(), this._bufferId)\n\n        if (currentWindow.top !== this._topLine || currentWindow.bottom !== this._bottomLine) {\n            Log.verbose(\n                \"[SyntaxHighlightingPeriodicJob.execute] Completing without doing work, as window size has changed.\",\n            )\n            return true\n        }\n\n        while (true) {\n            const current = new Date().getTime()\n\n            if (current - start > SYNTAX_JOB_BUDGET) {\n                Log.verbose(\n                    \"[SyntaxHighlightingPeriodicJob.execute] Pending due to exceeding budget.\",\n                )\n                return false\n            }\n\n            const currentState = this._store.getState()\n            const bufferState = currentState.bufferToHighlights[this._bufferId]\n\n            if (!bufferState) {\n                return true\n            }\n\n            const anyDirty = this._tokenizeFirstDirtyLine(bufferState)\n\n            if (!anyDirty) {\n                return true\n            }\n        }\n    }\n\n    private _tokenizeFirstDirtyLine(\n        state: SyntaxHighlighting.IBufferSyntaxHighlightState,\n    ): boolean {\n        let index = this._topLine\n\n        while (index <= this._bottomLine) {\n            const line = state.lines[index]\n\n            if (!line) {\n                break\n            }\n\n            if (!line.dirty) {\n                index++\n                continue\n            }\n\n            const previousStack = index === 0 ? null : state.lines[index - 1].ruleStack\n            const tokenizeResult = this._grammar.tokenizeLine(line.line, previousStack)\n\n            const tokens = tokenizeResult.tokens.map((t: any) => ({\n                range: types.Range.create(index, t.startIndex, index, t.endIndex),\n                scopes: t.scopes,\n            }))\n\n            const ruleStack = tokenizeResult.ruleStack\n\n            this._store.dispatch({\n                type: \"SYNTAX_UPDATE_TOKENS_FOR_LINE\",\n                bufferId: state.bufferId,\n                lineNumber: index,\n                tokens,\n                ruleStack,\n                version: state.version,\n            })\n\n            return true\n        }\n\n        return false\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/SyntaxHighlightingReducer.ts",
    "content": "// SyntaxHighlightingReducer.ts\r\n//\r\n// Reducers for handling state changes from ISyntaxHighlightActions\r\n\r\nimport {\r\n    IBufferSyntaxHighlightState,\r\n    ISyntaxHighlightAction,\r\n    ISyntaxHighlightState,\r\n    SyntaxHighlightLines,\r\n} from \"./SyntaxHighlightingStore\"\r\n\r\nimport { Reducer } from \"redux\"\r\n\r\nexport const reducer: Reducer<ISyntaxHighlightState> = (\r\n    state: ISyntaxHighlightState = {\r\n        bufferToHighlights: {},\r\n    },\r\n    action: ISyntaxHighlightAction,\r\n) => {\r\n    const newState = state\r\n\r\n    return {\r\n        ...newState,\r\n        bufferToHighlights: bufferToHighlightsReducer(state.bufferToHighlights, action),\r\n    }\r\n}\r\n\r\nexport const bufferToHighlightsReducer: Reducer<{\r\n    [bufferId: string]: IBufferSyntaxHighlightState\r\n}> = (\r\n    state: { [bufferId: string]: IBufferSyntaxHighlightState } = {},\r\n    action: ISyntaxHighlightAction,\r\n) => {\r\n    return {\r\n        ...state,\r\n        [action.bufferId]: bufferReducer(state[action.bufferId], action),\r\n    }\r\n}\r\n\r\nexport const bufferReducer: Reducer<IBufferSyntaxHighlightState> = (\r\n    state: IBufferSyntaxHighlightState = {\r\n        bufferId: null,\r\n        extension: null,\r\n        language: null,\r\n        version: -1,\r\n        topVisibleLine: -1,\r\n        bottomVisibleLine: -1,\r\n        insertModeLine: null,\r\n        lines: {},\r\n    },\r\n    action: ISyntaxHighlightAction,\r\n) => {\r\n    switch (action.type) {\r\n        case \"SYNTAX_RESET_BUFFER\":\r\n            return {\r\n                ...state,\r\n                lines: linesReducer(state.lines, action),\r\n            }\r\n        case \"SYNTAX_UPDATE_BUFFER\":\r\n            return {\r\n                ...state,\r\n                bufferId: action.bufferId,\r\n                language: action.language,\r\n                extension: action.extension,\r\n                lines: linesReducer(state.lines, action),\r\n                version: action.version,\r\n            }\r\n        case \"SYNTAX_UPDATE_BUFFER_VIEWPORT\":\r\n            return {\r\n                ...state,\r\n                topVisibleLine: action.topVisibleLine,\r\n                bottomVisibleLine: action.bottomVisibleLine,\r\n            }\r\n        case \"SYNTAX_UPDATE_TOKENS_FOR_LINE\":\r\n            return {\r\n                ...state,\r\n                lines: linesReducer(state.lines, action),\r\n            }\r\n        case \"SYNTAX_UPDATE_TOKENS_FOR_LINE_INSERT_MODE\":\r\n            return {\r\n                ...state,\r\n                insertModeLine: {\r\n                    version: action.version,\r\n                    lineNumber: action.lineNumber,\r\n                    info: {\r\n                        line: action.line,\r\n                        tokens: action.tokens,\r\n                        ruleStack: action.ruleStack,\r\n                        dirty: false,\r\n                    },\r\n                },\r\n            }\r\n        default:\r\n            return state\r\n    }\r\n}\r\n\r\nexport const linesReducer: Reducer<SyntaxHighlightLines> = (\r\n    state: SyntaxHighlightLines = {},\r\n    action: ISyntaxHighlightAction,\r\n) => {\r\n    switch (action.type) {\r\n        case \"SYNTAX_UPDATE_TOKENS_FOR_LINE\": {\r\n            const newState = {\r\n                ...state,\r\n            }\r\n\r\n            const originalLine = newState[action.lineNumber]\r\n\r\n            // If the ruleStack changed, we need to invalidate the next line\r\n            const shouldDirtyNextLine =\r\n                originalLine &&\r\n                originalLine.ruleStack &&\r\n                !originalLine.ruleStack.equals(action.ruleStack)\r\n\r\n            newState[action.lineNumber] = {\r\n                ...originalLine,\r\n                dirty: false,\r\n                tokens: action.tokens,\r\n                ruleStack: action.ruleStack,\r\n                version: action.version,\r\n            }\r\n\r\n            const nextLine = newState[action.lineNumber + 1]\r\n            if (shouldDirtyNextLine && nextLine) {\r\n                newState[action.lineNumber + 1] = {\r\n                    ...nextLine,\r\n                    dirty: true,\r\n                }\r\n            }\r\n            return newState\r\n        }\r\n        case \"SYNTAX_RESET_BUFFER\":\r\n            const resetState = Object.entries(state).reduce<SyntaxHighlightLines>(\r\n                (newResetState, [lineNumber, line]) => {\r\n                    newResetState[lineNumber] = {\r\n                        tokens: [],\r\n                        ruleStack: null,\r\n                        ...line,\r\n                        dirty: true,\r\n                    }\r\n                    return newResetState\r\n                },\r\n                {},\r\n            )\r\n            return resetState\r\n\r\n        case \"SYNTAX_UPDATE_BUFFER\":\r\n            const updatedBufferState: SyntaxHighlightLines = {\r\n                ...state,\r\n            }\r\n\r\n            for (let i = 0; i < action.lines.length; i++) {\r\n                const oldLine = updatedBufferState[i]\r\n                const newLine = action.lines[i]\r\n\r\n                // check if the buffer version has changed and if so\r\n                // update the line - rather than check if specific line\r\n                // is changed\r\n                if (oldLine && oldLine.version >= action.version) {\r\n                    continue\r\n                }\r\n\r\n                updatedBufferState[i] = {\r\n                    tokens: [],\r\n                    ruleStack: null,\r\n                    ...oldLine,\r\n                    line: newLine,\r\n                    dirty: true,\r\n                }\r\n            }\r\n\r\n            return updatedBufferState\r\n    }\r\n\r\n    return state\r\n}\r\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/SyntaxHighlightingStore.ts",
    "content": "/**\n * SyntaxHighlighting.ts\n *\n * Handles enhanced syntax highlighting\n */\n\nimport { Store } from \"redux\"\nimport * as types from \"vscode-languageserver-types\"\nimport { StackElement } from \"vscode-textmate\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as PeriodicJobs from \"./../../PeriodicJobs\"\nimport { createStore } from \"./../../Redux\"\nimport { configuration } from \"./../Configuration\"\n\nimport { GrammarLoader } from \"./GrammarLoader\"\nimport { SyntaxHighlightingPeriodicJob } from \"./SyntaxHighlightingPeriodicJob\"\nimport { reducer } from \"./SyntaxHighlightingReducer\"\nimport * as Selectors from \"./SyntaxHighlightSelectors\"\n\nconst syntaxHighlightingJobs = new PeriodicJobs.PeriodicJobManager()\n\nexport interface ISyntaxHighlightTokenInfo {\n    scopes: string[]\n    range: types.Range\n}\n\nexport interface ISyntaxHighlightLineInfo {\n    line: string\n    ruleStack: StackElement\n    tokens: ISyntaxHighlightTokenInfo[]\n    dirty: boolean\n\n    // The last version of the line that was 'tokenized'\n    version?: number\n}\n\nexport interface SyntaxHighlightLines {\n    [key: number]: ISyntaxHighlightLineInfo\n}\n\n// This tracks the last insert-mode line modified\nexport interface InsertModeLineState {\n    version: number\n    lineNumber: number\n    info: ISyntaxHighlightLineInfo\n}\n\nexport interface IBufferSyntaxHighlightState {\n    bufferId: string\n    language: string\n    extension: string\n    version: number\n\n    // This doesn't work quite right if we have a buffer open in a separate window...\n    topVisibleLine: number\n    bottomVisibleLine: number\n\n    insertModeLine: InsertModeLineState | null\n\n    lines: SyntaxHighlightLines\n}\n\nexport interface ISyntaxHighlightState {\n    bufferToHighlights: {\n        [bufferId: string]: IBufferSyntaxHighlightState\n    }\n}\n\nexport const DefaultSyntaxHighlightState: ISyntaxHighlightState = {\n    bufferToHighlights: {},\n}\n\nexport type ISyntaxHighlightAction =\n    | {\n          type: \"SYNTAX_RESET_BUFFER\"\n          bufferId: string\n      }\n    | {\n          type: \"SYNTAX_UPDATE_BUFFER\"\n          language: string\n          extension: string\n          bufferId: string\n          lines: string[]\n          version: number\n      }\n    | {\n          type: \"SYNTAX_UPDATE_BUFFER_LINE\"\n          bufferId: string\n          lineNumber: number\n          line: string\n          version: number\n      }\n    | {\n          type: \"SYNTAX_UPDATE_TOKENS_FOR_LINE\"\n          bufferId: string\n          lineNumber: number\n          tokens: ISyntaxHighlightTokenInfo[]\n          ruleStack: StackElement\n          version: number\n      }\n    | {\n          type: \"SYNTAX_UPDATE_TOKENS_FOR_LINE_INSERT_MODE\"\n          bufferId: string\n          line: string\n          lineNumber: number\n          tokens: ISyntaxHighlightTokenInfo[]\n          ruleStack: StackElement\n          version: number\n      }\n    | {\n          type: \"SYNTAX_UPDATE_BUFFER_VIEWPORT\"\n          bufferId: string\n          topVisibleLine: number\n          bottomVisibleLine: number\n      }\n\nconst grammarLoader = new GrammarLoader()\n\n// Middleware that handles insert-mode updates\n// For insert-mode updates, we'll resolve them immediately and apply them ephemerally\nconst updateBufferLineMiddleware = (store: any) => (next: any) => (action: any) => {\n    const result: ISyntaxHighlightAction = next(action)\n\n    if (action.type === \"SYNTAX_UPDATE_BUFFER_LINE\") {\n        const state: ISyntaxHighlightState = store.getState()\n        const bufferId = action.bufferId\n\n        if (!state.bufferToHighlights[bufferId]) {\n            return result\n        }\n\n        const buffer = state.bufferToHighlights[bufferId]\n\n        const language = buffer.language\n        const extension = buffer.extension\n\n        if (!language || !extension) {\n            return result\n        }\n\n        if (buffer.version > action.version) {\n            return result\n        }\n\n        grammarLoader.getGrammarForLanguage(language, extension).then(grammar => {\n            if (!grammar) {\n                return\n            }\n\n            // We'll resolve the tokens for\n            const previousRuleStack =\n                action.lineNumber === 0 ? null : buffer.lines[action.lineNumber - 1].ruleStack\n            const tokenizeResult = grammar.tokenizeLine(action.line, previousRuleStack)\n\n            const tokens = tokenizeResult.tokens.map(token => ({\n                range: types.Range.create(\n                    action.lineNumber,\n                    token.startIndex,\n                    action.lineNumber,\n                    token.endIndex,\n                ),\n                scopes: token.scopes,\n            }))\n\n            const updateInsertLineAction: ISyntaxHighlightAction = {\n                type: \"SYNTAX_UPDATE_TOKENS_FOR_LINE_INSERT_MODE\",\n                line: action.line,\n                lineNumber: action.lineNumber,\n                bufferId: buffer.bufferId,\n                version: action.version,\n                ruleStack: tokenizeResult.ruleStack,\n                tokens,\n            }\n\n            store.dispatch(updateInsertLineAction)\n        })\n    }\n\n    return result\n}\n\nconst updateTokenMiddleware = (store: any) => (next: any) => (action: any) => {\n    const result: ISyntaxHighlightAction = next(action)\n\n    if (\n        action.type === \"SYNTAX_UPDATE_BUFFER\" ||\n        action.type === \"SYNTAX_UPDATE_BUFFER_VIEWPORT\" ||\n        action.type === \"SYNTAX_RESET_BUFFER\"\n    ) {\n        const state: ISyntaxHighlightState = store.getState()\n        const bufferId = action.bufferId\n\n        const language = state.bufferToHighlights[bufferId].language\n        const extension = state.bufferToHighlights[bufferId].extension\n\n        if (!language || !extension) {\n            return result\n        }\n\n        grammarLoader.getGrammarForLanguage(language, extension).then(grammar => {\n            if (!grammar) {\n                return\n            }\n\n            const buffer = state.bufferToHighlights[bufferId]\n\n            if (\n                Object.keys(buffer.lines).length >=\n                configuration.getValue(\"editor.textMateHighlighting.maxLines\")\n            ) {\n                Log.info(\n                    \"[SyntaxHighlighting - fullBufferUpdateEpic]: Not applying syntax highlighting as the maxLines limit was exceeded\",\n                )\n                return\n            }\n\n            const relevantRange = Selectors.getRelevantRange(state, bufferId)\n\n            syntaxHighlightingJobs.startJob(\n                new SyntaxHighlightingPeriodicJob(\n                    store,\n                    action.bufferId,\n                    grammar,\n                    relevantRange.top,\n                    relevantRange.bottom,\n                ),\n            )\n        })\n    }\n\n    return result\n}\n\nexport const createSyntaxHighlightStore = (): Store<ISyntaxHighlightState> => {\n    const syntaxHighlightStore: Store<ISyntaxHighlightState> = createStore(\n        \"SyntaxHighlighting\",\n        reducer,\n        DefaultSyntaxHighlightState,\n        [updateTokenMiddleware, updateBufferLineMiddleware],\n    )\n\n    return syntaxHighlightStore\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/TokenGenerator.tsx",
    "content": "import * as path from \"path\"\nimport * as types from \"vscode-languageserver-types\"\nimport { StackElement } from \"vscode-textmate\"\n\nimport { editorManager } from \"../../Services/EditorManager\"\nimport { GrammarLoader } from \"../../Services/SyntaxHighlighting/GrammarLoader\"\n\nexport interface IGrammarToken {\n    scopes: any\n    range: types.Range\n}\n\nexport interface IHighlight {\n    foreground: number\n    background?: number\n    bold?: boolean\n    italic?: boolean\n}\n\ninterface IGetTokens {\n    line: string\n    language: string\n    extension?: string\n}\n\nexport interface IGrammarPerLine {\n    [line: number]: IGrammarTokens\n}\n\nexport interface IGrammarTokens {\n    tokens: IGrammarToken[]\n    ruleStack: StackElement\n    line: string\n}\n\n/**\n * This function takes a language, its extension, and a line/lines\n * and it returns an object with keys representing each line as a number\n * each key has a value of the line, the line's associated tokens and the rulestack\n * @returns {IGrammarPerLine}\n */\nexport const getTokens = (Grammar: GrammarLoader) => async ({\n    language,\n    extension,\n    line,\n}: IGetTokens): Promise<IGrammarPerLine> => {\n    let lang = language\n    let ext = extension\n\n    if (!language || !extension) {\n        const { activeBuffer: b } = editorManager.activeEditor\n        lang = language || b.language\n        ext = extension || path.extname(b.filePath)\n    }\n\n    const grammar = await Grammar.getGrammarForLanguage(lang, ext)\n\n    let tokens = null\n    let ruleStack = null\n\n    if (grammar) {\n        const lines = line.split(/\\n/)\n        const tokensPerLine: IGrammarPerLine = {}\n        for (let index = 0; index < lines.length; index++) {\n            const tokenizeResult = grammar.tokenizeLine(lines[index], ruleStack)\n            tokens = tokenizeResult.tokens.map((t: any) => ({\n                range: types.Range.create(index, t.startIndex, index, t.endIndex),\n                scopes: t.scopes,\n            }))\n            ruleStack = tokenizeResult.ruleStack\n            tokensPerLine[index] = { tokens, ruleStack, line: lines[index] }\n        }\n        return tokensPerLine\n    }\n    return { 0: { tokens: [], ruleStack: null, line: null } }\n}\n\nconst grammarloader = new GrammarLoader()\nexport default getTokens(grammarloader)\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/TokenScorer.ts",
    "content": "import { TokenColor } from \"./../TokenColors\"\n\ninterface TokenRanking {\n    depth: number\n    highestRankedToken: TokenColor\n}\n\n/**\n * Determines the correct token to render for a particular item\n * in a line based on textmate highlighting rules\n * @name TokenScorer\n * @class\n */\nexport class TokenScorer {\n    /**\n     * meta tokens are not intended for syntax highlighting but for other types of plugins\n     * source is a token that All items are given effectively giving it no value from the\n     * point of view of syntax highlighting as it distinguishes nothing\n     *\n     * see: https://www.sublimetext.com/docs/3/scope_naming.html\n     */\n    private _BANNED_TOKENS = [\"meta\", \"source\"]\n    private readonly _SCOPE_PRIORITIES = {\n        support: 1,\n    }\n\n    /**\n     * rankTokenScopes\n     *  If more than one scope selector matches the current scope then they are ranked\n     *  according to how “good” a match they each are. The winner is the scope selector\n     *  which (in order of precedence):\n     *  1. Match the element deepest down in the scope e.g.\n     *    string wins over source.php when the scope is source.php string.quoted.\n     *  2. Match most of the deepest element e.g. string.quoted wins over string.\n     *  3. Rules 1 and 2 applied again to the scope selector when removing the deepest element\n     *    (in the case of a tie), e.g. text source string wins over source string.\n     *\n     * Reference: https://macromates.com/manual/en/scope_selectors\n     *\n     * @name rankTokenScopes\n     * @function\n     * @param {string[]} scopes\n     * @param {TokenColor[]} themeColors\n     * @returns {TokenColor}\n     */\n    public rankTokenScopes(scopes: string[], themeColors: TokenColor[]): TokenColor {\n        const initialRanking: TokenRanking = { highestRankedToken: null, depth: null }\n        const { highestRankedToken } = scopes.reduce((highestSoFar, scope) => {\n            if (this._isBannedScope(scope)) {\n                return highestSoFar\n            }\n\n            const matchingToken = this._getMatchingToken(scope, themeColors)\n\n            if (!matchingToken) {\n                return highestSoFar\n            }\n\n            const depth = scope.split(\".\").length\n            if (depth === highestSoFar.depth) {\n                const highestPrecedence = this._determinePrecedence(\n                    matchingToken,\n                    highestSoFar.highestRankedToken,\n                )\n                return { highestRankedToken: highestPrecedence, depth }\n            }\n            if (depth > highestSoFar.depth) {\n                return { highestRankedToken: matchingToken, depth }\n            }\n            return highestSoFar\n        }, initialRanking)\n        return highestRankedToken || null\n    }\n\n    private _isBannedScope = (scope: string) => {\n        return this._BANNED_TOKENS.some(token => scope.includes(token))\n    }\n\n    private _getPriority = (token: TokenColor) => {\n        const priorities = Object.keys(this._SCOPE_PRIORITIES)\n        return priorities.reduce(\n            (acc, priority) =>\n                token.scope.includes(priority) && this._SCOPE_PRIORITIES[priority] < acc.priority\n                    ? { priority: this._SCOPE_PRIORITIES[priority], token }\n                    : acc,\n            { priority: 0, token },\n        )\n    }\n\n    /**\n     * Assign each token a priority based on `SCOPE_PRIORITIES` and then\n     * sort by priority take the first aka the highest priority one\n     *\n     * @name _determinePrecedence\n     * @function\n     * @param {TokenColor[]} ...tokens\n     * @returns {TokenColor}\n     */\n    private _determinePrecedence(...tokens: TokenColor[]): TokenColor {\n        const [{ token }] = tokens\n            .map(this._getPriority)\n            .sort((prev, next) => next.priority - prev.priority)\n        return token\n    }\n\n    /**\n     * if the lowest scope level doesn't match then we go up one level\n     * i.e. constant.numeric.special -> constant.numeric\n     * and search the theme colors for a match\n     *\n     * @name _getMatchingToken\n     * @function\n     * @param {string} scope\n     * @param {TokenColor[]} theme\n     * @returns {TokenColor}\n     */\n    private _getMatchingToken(scope: string, theme: TokenColor[]): TokenColor {\n        const parts = scope.split(\".\")\n        if (parts.length < 2) {\n            return null\n        }\n        const matchingToken = theme.find(color => color.scope.includes(scope))\n        if (matchingToken) {\n            return matchingToken\n        }\n        const currentScope = parts.slice(0, parts.length - 1).join(\".\")\n        return this._getMatchingToken(currentScope, theme)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/TokenThemeProvider.tsx",
    "content": "import * as React from \"react\"\nimport { css, ThemeProvider, withTheme } from \"styled-components\"\n\nimport { TokenColor, TokenColorStyle } from \"./../../Services/TokenColors\"\nimport { Css, IThemeColors } from \"./../../UI/components/common\"\n\n/**\n * A object representing a key of default oni tokens and an array of tokens\n * to create based of of the colors of the default token\n */\nconst defaultsToMap = {\n    \"variable.parameter\": [\n        \"support\",\n        \"support.variable\",\n        \"support.variable.property.dom\",\n        \"support.variable.dom\",\n        \"support.class.dom\",\n        \"support.type.builtin\",\n        \"support.class.builtin\",\n        \"support.type.primitive\",\n        \"support.variable.property\",\n        \"variable.language\",\n        \"variable.language.this\",\n        \"variable.function\",\n        \"variable.parameter\",\n        \"variable.object\",\n        \"variable\",\n        \"meta.object.type\",\n        \"meta.object\",\n        \"variable.other.readwrite\",\n        \"variable.other.readwrite.alias\",\n        \"constant.numeric\",\n        \"constant.language\",\n        \"constant.numeric.integer\",\n        \"constant.character.escape\",\n    ],\n    \"support.function\": [\n        \"invalid\",\n        \"function\",\n        \"support.function\",\n        \"entity.name\",\n        \"entity.name.section\",\n        \"entity.name.type\",\n        \"entity.name.tag\",\n        \"entity.name.type.alias\",\n        \"entity.name.type.class\",\n        \"entity.name.function\",\n        \"entity.name.type.enum\",\n        \"entity.name.type.interface\",\n        \"entity.name.type.module\",\n        \"entity.other.attribute.name\",\n        \"entity.other.inherited-class\",\n        \"entity.other.attribute.name\",\n        \"punctuation.accessor\",\n        \"punctuation.separator.continuation\",\n        \"punctuation.separator.comma\",\n        \"punctuation.terminator\",\n        \"punctuation.terminator\",\n    ],\n    \"variable.other.constant\": [\n        \"constant\",\n        \"constant.language\",\n        \"variable.other\",\n        \"entity.other\",\n        \"keyword\",\n        \"keyword.package\",\n        \"keyword.var\",\n        \"keyword.const\",\n        \"keyword.struct\",\n        \"keyword.control\",\n        \"keyword.function\",\n        \"keyword.operator\",\n        \"keyword.operator.expression\",\n        \"keyword.operator.expression.void\",\n        \"keyword.control.import\",\n        \"storage.type\",\n        \"storage.modifier\",\n        \"storage.type.type\",\n        \"storage.type.class\",\n        \"storage.type.enum\",\n        \"storage.type.string\",\n        \"storage.type.interface\",\n        \"storage.type.function\",\n        \"storage.type.namespace\",\n        \"keyword.control.import\",\n        \"keyword.control.default\",\n        \"keyword.control.export\",\n        \"variable.object\",\n        \"variable.object.property\",\n        \"variable.other.constant\",\n        \"variable.other.object\",\n        \"variable.other.assignment\",\n        \"variable.other.declaration\",\n        \"variable.other.constant.object\",\n        \"variable.other.object.property\",\n        \"variable.other.property\",\n    ],\n    \"string.quoted.double\": [\n        \"string.quoted.double\",\n        \"string.quoted.single\",\n        \"string.quoted.triple\",\n        \"string\",\n        \"string.other\",\n    ],\n}\n\ntype TokenFunc = (theme: INewTheme) => string\n\nexport interface INewTheme extends IThemeColors {\n    \"editor.tokenColors.hoverTokens\": {\n        [token: string]: TokenColorStyle\n    }\n}\n\ninterface IDefaultMap {\n    [defaultTokens: string]: string[]\n}\n\ninterface RenderProps {\n    theme: INewTheme\n    styles: Css\n}\n\ninterface IProps {\n    render: (s: RenderProps) => React.ReactElement<RenderProps> | React.ReactNode\n    theme: INewTheme\n    defaultMap?: IDefaultMap\n    tokenColors?: TokenColor[]\n}\n\ninterface IState {\n    theme: INewTheme\n    styles: Css\n}\n\ninterface IGenerateTokenArgs {\n    defaultMap?: IDefaultMap\n    defaultTokens: TokenColor[]\n}\n\ntype Style = \"bold\" | \"italic\" | \"foreground\" | \"background\"\n\n/**\n * **TokenThemeProvider** is a Render Prop\n * It is designed to be used to give UI components access to a\n * theme with token colors as an accessible object as well as associated\n * styles for the tokens.\n * It wraps the component it renders in a separate theme which shares values with the\n * main theme but adds on token colors to the theme as `\"editor.tokenColors.hoverTokens\"`\n * It takes the basic token colors and generates a larger set based on the existing\n * by copying the settings of the default ones this can be customised by passing a different set\n * of defaults as props\n */\nclass TokenThemeProvider extends React.Component<IProps, IState> {\n    public state: IState = {\n        styles: null,\n        theme: this.props.theme,\n    }\n\n    public flattenedDefaults = Object.values(defaultsToMap).reduce((acc, a) => [...acc, ...a], [])\n\n    public componentDidMount() {\n        const themeTokenNames = this.convertTokenNamesToClasses(this.props.tokenColors)\n        const tokensToHightlight = [...themeTokenNames, ...this.flattenedDefaults]\n        const styles = this.constructStyles(tokensToHightlight)\n        const editorTokens = this.createThemeFromTokens(this.props.tokenColors)\n\n        const theme = { ...this.props.theme, ...editorTokens }\n        this.setState({ theme, styles })\n    }\n\n    public createThemeFromTokens(tokens: TokenColor[]) {\n        const combinedThemeAndDefaultTokens = this.generateTokens({\n            defaultTokens: this.props.tokenColors,\n        })\n        const tokenColorsMap = combinedThemeAndDefaultTokens.reduce(\n            (theme, token) => {\n                return {\n                    ...theme,\n                    [token.scope]: {\n                        ...token.settings,\n                    },\n                }\n            },\n            {} as { [key: string]: TokenColorStyle },\n        )\n\n        return { \"editor.tokenColors.hoverTokens\": tokenColorsMap }\n    }\n\n    public generateTokens({ defaultMap = defaultsToMap, defaultTokens }: IGenerateTokenArgs) {\n        const newTokens = Object.keys(defaultMap).reduce((acc, defaultTokenName) => {\n            const defaultToken = this.props.tokenColors.find(token =>\n                token.scope.includes(defaultTokenName),\n            )\n            if (defaultToken) {\n                const tokens = defaultMap[defaultTokenName].map(name =>\n                    this.generateSingleToken(name, defaultToken),\n                )\n                return [...acc, ...tokens]\n            }\n            return acc\n        }, [])\n        return [...newTokens, ...this.props.tokenColors]\n    }\n\n    public generateSingleToken(name: string, { settings }: TokenColor) {\n        return {\n            scope: name,\n            settings,\n        }\n    }\n\n    /**\n     * Provides a check that a token exists and has valid values\n     * if not it returns nothing or in the case of the foregroundColor it returns a default\n     * @returns {string}\n     */\n    public getCssRule = (\n        hoverTokens: INewTheme[\"editor.tokenColors.hoverTokens\"],\n        token: string,\n        style: Style,\n    ) => {\n        const details = hoverTokens[token]\n\n        if (!details) {\n            return \"\"\n        }\n\n        const italicOrBold = details.fontStyle && details.fontStyle.includes(style)\n\n        switch (style) {\n            case \"italic\":\n                return italicOrBold ? \"font-style: italic\" : \"\"\n            case \"bold\":\n                return italicOrBold ? \"font-weight: bold\" : \"\"\n            case \"foreground\":\n            default:\n                return details[style] ? `color: ${details[style]}` : \"\"\n        }\n    }\n    /**\n     * Construct Class is a function which takes a token\n     * and returns another function which takes the theme as an argument\n     * with which it creates a css class based on the token name and returns this as a string\n     * @returns {fn(theme) => string}\n     */\n    public constructClassName = (token: string) => (theme: INewTheme) => {\n        const tokenAsClass = token.replace(/[.]/g, \"-\")\n\n        const hoverTokens = theme[\"editor.tokenColors.hoverTokens\"]\n\n        if (!hoverTokens || !(token in hoverTokens)) {\n            return \"\"\n        }\n\n        const foreground = this.getCssRule(hoverTokens, token, \"foreground\")\n        const italics = this.getCssRule(hoverTokens, token, \"italic\")\n        const bold = this.getCssRule(hoverTokens, token, \"bold\")\n        const hasContent = foreground || italics || bold\n\n        if (!hasContent) {\n            return \"\"\n        }\n\n        const cssClass = `\n            .${tokenAsClass} {\n                ${bold};\n                ${italics};\n                ${foreground};\n            }\n        `\n        return cssClass\n    }\n\n    public convertTokenNamesToClasses = (tokenArray: TokenColor[]) => {\n        const arrayOfArrays = tokenArray.map(token => token.scope)\n        const names = [].concat(...arrayOfArrays)\n        return names\n    }\n\n    public constructStyles = (tokensToMap: string[] = this.flattenedDefaults) => {\n        const symbols = tokensToMap.map(this.constructClassName)\n\n        const flattenSymbols = (theme: INewTheme, fns: TokenFunc[]) =>\n            fns.map(fn => fn(theme)).join(\"\\n\")\n\n        const styles = css`\n            ${p => flattenSymbols(p.theme, symbols)};\n        `\n        return styles\n    }\n\n    public render() {\n        const { theme, styles } = this.state\n        return (\n            theme && (\n                <ThemeProvider theme={theme}>{this.props.render({ theme, styles })}</ThemeProvider>\n            )\n        )\n    }\n}\n\nexport default withTheme(TokenThemeProvider)\n"
  },
  {
    "path": "browser/src/Services/SyntaxHighlighting/index.ts",
    "content": "export * from \"./Definitions\"\nexport * from \"./ISyntaxHighlighter\"\nexport * from \"./SyntaxHighlighting\"\nexport * from \"./SyntaxHighlightReconciler\"\nexport * from \"./SyntaxHighlightingReducer\"\nexport * from \"./SyntaxHighlightingStore\"\n"
  },
  {
    "path": "browser/src/Services/Tasks.ts",
    "content": "/**\n * Tasks.ts\n *\n * Manages the 'tasks' pane / Command Palette\n *\n * Tasks encompass a few different pieces of functionality:\n *  - Launch parameters from a .oni folder\n *  - Plugin commands\n *  - NPM tasks\n */\n\nimport { remote } from \"electron\"\nimport * as find from \"lodash/find\"\nimport * as flatten from \"lodash/flatten\"\n\nimport * as Oni from \"oni-api\"\n\nimport { Menu, MenuManager } from \"./../Services/Menu\"\n\nimport { render as renderKeyBindingInfo } from \"./../UI/components/KeyBindingInfo\"\n\nexport interface ITask {\n    name: string\n    detail: string\n    command: string\n    messageSuccess?: string\n    messageFail?: string // TODO: implement callbacks to return boolean\n    callback: () => void\n}\n\nexport interface ITaskProvider {\n    getTasks(): Promise<ITask[]>\n}\n\nexport class Tasks {\n    private _lastTasks: ITask[] = []\n    private _menu: Menu\n    private _providers: ITaskProvider[] = []\n\n    constructor(private _menuManager: MenuManager) {}\n\n    // TODO: This should be refactored, as it is simply\n    // a timing dependency on when the object is created versus when\n    // it is shown.\n    public registerTaskProvider(taskProvider: ITaskProvider): void {\n        this._providers.push(taskProvider)\n    }\n\n    public show(): void {\n        this._refreshTasks().then(() => {\n            const options: Oni.Menu.MenuOption[] = this._lastTasks\n                .filter(t => t.name || t.detail)\n                .map(f => {\n                    return {\n                        label: f.name,\n                        detail: f.detail,\n                        additionalComponent: renderKeyBindingInfo({ command: f.command }),\n                    }\n                })\n\n            this._menu = this._menuManager.create()\n            this._menu.onItemSelected.subscribe((selection: any) => this._onItemSelected(selection))\n            this._menu.show()\n            this._menu.setItems(options)\n        })\n    }\n\n    private async _onItemSelected(selectedOption: Oni.Menu.MenuOption): Promise<void> {\n        if (!selectedOption) {\n            return\n        }\n\n        const { label, detail } = selectedOption\n\n        const selectedTask = find(this._lastTasks, t => t.name === label && t.detail === detail)\n\n        if (selectedTask) {\n            await selectedTask.callback()\n\n            // TODO: we should make the callback return a bool so we can display either success/fail messages\n            if (selectedTask.messageSuccess != null) {\n                remote.dialog.showMessageBox({\n                    type: \"info\",\n                    title: \"Success\",\n                    message: selectedTask.messageSuccess,\n                })\n            }\n        }\n    }\n\n    private async _refreshTasks(): Promise<void> {\n        this._lastTasks = []\n\n        const initialProviders: ITaskProvider[] = []\n        const taskProviders = initialProviders.concat(this._providers)\n        const allTasks = await Promise.all(\n            taskProviders.map(async (t: ITaskProvider) => (await t.getTasks()) || []),\n        )\n        this._lastTasks = flatten(allTasks)\n    }\n}\n\nlet _tasks: Tasks = null\n\nexport const activate = (menuManager: MenuManager) => {\n    _tasks = new Tasks(menuManager)\n}\n\nexport const getInstance = (): Tasks => {\n    return _tasks\n}\n"
  },
  {
    "path": "browser/src/Services/Terminal.ts",
    "content": "/**\n * Terminal.ts\n *\n * Helper / convenience commands for Neovim's integrated terminal experience\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { CommandManager } from \"./CommandManager\"\nimport { Configuration } from \"./Configuration\"\nimport { EditorManager } from \"./EditorManager\"\n\nexport const activate = (\n    commandManager: CommandManager,\n    configuration: Configuration,\n    editorManager: EditorManager,\n) => {\n    const openTerminal = async (openMode: Oni.FileOpenMode) => {\n        const terminalCommand =\n            configuration.getValue(\"terminal.shellCommand\") ||\n            (await editorManager.activeEditor.neovim.callFunction(\"nvim_get_option\", [\"shell\"]))\n\n        editorManager.activeEditor.openFile(`term://${terminalCommand}`, { openMode })\n    }\n\n    commandManager.registerCommand({\n        command: \"terminal.openInVerticalSplit\",\n        name: \"Terminal: Open Vertical\",\n        detail: \"Open a terminal emulator in a vertical split\",\n        execute: () => openTerminal(Oni.FileOpenMode.VerticalSplit),\n    })\n\n    commandManager.registerCommand({\n        command: \"terminal.openInHorizontalSplit\",\n        name: \"Terminal: Open Horizontal\",\n        detail: \"Open a terminal emulator in a horizontal split\",\n        execute: () => openTerminal(Oni.FileOpenMode.HorizontalSplit),\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/Themes/ThemeLoader.ts",
    "content": "/**\n * ThemeLoader\n *\n * - Manages loading of themes\n */\n\nimport * as fs from \"fs\"\n\nimport { DefaultTheme, IThemeMetadata } from \"./ThemeManager\"\n\nimport { IThemeContribution } from \"./../../Plugins/Api/Capabilities\"\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nexport interface IThemeLoader {\n    getAllThemes(): Promise<IThemeContribution[]>\n    getThemeByName(name: string): Promise<IThemeMetadata>\n}\n\nexport class DefaultLoader implements IThemeLoader {\n    public async getAllThemes(): Promise<IThemeContribution[]> {\n        return Promise.resolve([])\n    }\n\n    public async getThemeByName(name: string): Promise<IThemeMetadata> {\n        return DefaultTheme\n    }\n}\n\nexport class PluginThemeLoader implements IThemeLoader {\n    constructor(private _pluginManager: PluginManager) {}\n\n    public async getAllThemes(): Promise<IThemeContribution[]> {\n        const plugins = this._pluginManager.plugins\n\n        const pluginsWithThemes = plugins.filter(p => {\n            return p.metadata && p.metadata.contributes && p.metadata.contributes.themes\n        })\n\n        const allThemes = pluginsWithThemes.reduce(\n            (previous: IThemeContribution[], current) => {\n                const themes = current.metadata.contributes.themes\n                return [...previous, ...themes]\n            },\n            [] as IThemeContribution[],\n        )\n\n        return allThemes\n    }\n\n    public async getThemeByName(name: string): Promise<IThemeMetadata> {\n        const allThemes = await this.getAllThemes()\n\n        const matchingTheme = allThemes.find(t => t.name === name)\n\n        if (!matchingTheme || !matchingTheme.path) {\n            return null\n        }\n\n        return this._loadThemeFromFile(matchingTheme.path)\n    }\n\n    private async _loadThemeFromFile(themeJsonPath: string): Promise<IThemeMetadata> {\n        const contents = await new Promise<string>((resolve, reject) => {\n            fs.readFile(themeJsonPath, \"utf8\", (err, data: string) => {\n                if (err) {\n                    reject(err)\n                    return\n                }\n\n                resolve(data)\n            })\n        })\n\n        return JSON.parse(contents) as IThemeMetadata\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Themes/ThemeManager.ts",
    "content": "/**\n * ThemeManager\n *\n * - Manages theming\n */\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { IThemeContribution } from \"./../../Plugins/Api/Capabilities\"\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { Configuration, configuration, GenericConfigurationValues } from \"./../Configuration\"\n\nimport * as PersistentSettings from \"./../Configuration/PersistentSettings\"\nimport { ThemeToken, TokenColor } from \"./../TokenColors\"\nimport { IThemeLoader, PluginThemeLoader } from \"./ThemeLoader\"\n\nexport interface IThemeColors {\n    background: string\n    foreground: string\n    \"editor.background\": string\n    \"editor.foreground\": string\n\n    \"highlight.mode.insert.foreground\": string\n    \"highlight.mode.insert.background\": string\n\n    \"highlight.mode.normal.foreground\": string\n    \"highlight.mode.normal.background\": string\n\n    \"highlight.mode.visual.foreground\": string\n    \"highlight.mode.visual.background\": string\n\n    \"highlight.mode.operator.foreground\": string\n    \"highlight.mode.operator.background\": string\n\n    \"tabs.background\": string\n    \"tabs.foreground\": string\n    \"tabs.borderBottom\": string\n    \"tabs.active.foreground\": string\n    \"tabs.active.background\": string\n\n    \"scrollbar.track\": string\n    \"scrollbar.thumb\": string\n    \"scrollbar.thumb.hover\": string\n\n    // Tool tip is used for some contextual information,\n    // like hover, as well as for rename.\n    \"toolTip.background\": string\n    \"toolTip.foreground\": string\n    \"toolTip.border\": string\n\n    // User coloring options for the hover menu\n    \"editor.hover.title.background\": string\n    \"editor.hover.title.foreground\": string\n    \"editor.hover.border\": string\n    \"editor.hover.contents.background\": string\n    \"editor.hover.contents.foreground\": string\n    \"editor.hover.contents.codeblock.background\": string\n    \"editor.hover.contents.codeblock.foreground\": string\n\n    // Context menu is used for completion, refactoring\n    \"contextMenu.background\": string\n    \"contextMenu.foreground\": string\n    \"contextMenu.border\": string\n    \"contextMenu.highlight\": string\n\n    // Menu is used for the popup menu\n    \"menu.background\": string\n    \"menu.foreground\": string\n    \"menu.border\": string\n    \"menu.highlight\": string\n\n    \"sidebar.background\": string\n    \"sidebar.foreground\": string\n    \"sidebar.active.background\": string\n    \"sidebar.selection.border\": string\n\n    \"statusBar.background\": string\n    \"statusBar.foreground\": string\n\n    \"title.background\": string\n    \"title.foreground\": string\n\n    \"fileExplorer.background\": string\n    \"fileExplorer.foreground\": string\n    \"fileExplorer.selection.background\": string\n    \"fileExplorer.selection.foreground\": string\n    \"fileExplorer.cursor.background\": string\n    \"fileExplorer.cursor.foreground\": string\n\n    \"editor.tokenColors\": ThemeToken[]\n\n    // LATER:\n    //  - Notifications?\n    //  - Alert / message?\n}\n\nimport * as Color from \"color\"\n\n/**\n * Gets a reasonable border color for popup elements, based on popups\n */\nexport const getBorderColor = (bgColor: string, fgColor: string): string => {\n    const backgroundColor = Color(bgColor)\n    const foregroundColor = Color(fgColor)\n\n    const borderColor =\n        backgroundColor.luminosity() > 0.5\n            ? foregroundColor.lighten(0.6)\n            : foregroundColor.darken(0.6)\n    return borderColor.hex().toString()\n}\n\nexport const getBackgroundColor = (editorBackground: string): string => {\n    return Color(editorBackground)\n        .darken(0.25)\n        .hex()\n        .toString()\n}\n\nconst darken = (c: string, deg = 0.15) =>\n    Color(c)\n        .darken(0.15)\n        .hex()\n        .toString()\nconst alterColor = (c: string) => (Color(c).luminosity() > 0.5 ? darken(c) : darken(c, 0.6))\n\nexport const getHoverColors = (\n    userConfig: GenericConfigurationValues,\n    colors: Partial<IThemeColors>,\n) => {\n    const alteredBackground = alterColor(colors[\"toolTip.background\"])\n    const hoverDefaults = {\n        \"editor.hover.title.background\": alteredBackground,\n        \"editor.hover.title.foreground\": colors[\"toolTip.foreground\"],\n        \"editor.hover.border\": colors[\"toolTip.border\"],\n        \"editor.hover.contents.background\": alteredBackground,\n        \"editor.hover.contents.foreground\": colors[\"toolTip.foreground\"],\n        \"editor.hover.contents.codeblock.background\": darken(alteredBackground, 0.25),\n        \"editor.hover.contents.codeblock.foreground\": colors[\"toolTip.foreground\"],\n    }\n\n    const userHoverColors = Object.keys(userConfig)\n        .filter(value => value.includes(\"editor.hover\"))\n        .reduce((acc, val) => {\n            if (userConfig[val]) {\n                acc[val] = userConfig[val]\n            }\n            return acc\n        }, hoverDefaults)\n    return userHoverColors\n}\n\nexport const getColorsFromConfig = ({\n    config,\n    defaultTheme,\n    themeColors,\n}: {\n    config: Configuration\n    themeColors: Partial<IThemeColors>\n    defaultTheme: IThemeColors\n}) => {\n    const userConfig = config.getValues()\n    const hoverColors = getHoverColors(userConfig, themeColors)\n\n    return hoverColors\n}\n\nexport const getColorsFromBackgroundAndForeground = (\n    background: string,\n    foreground: string,\n): IThemeColors => {\n    const shellBackground = getBackgroundColor(background)\n    const borderColor = getBorderColor(background, foreground)\n    return {\n        ...DefaultThemeColors,\n        background: shellBackground,\n        foreground,\n        \"editor.background\": background,\n        \"editor.foreground\": foreground,\n\n        \"toolTip.background\": background,\n        \"toolTip.foreground\": foreground,\n        \"toolTip.border\": borderColor,\n\n        \"editor.hover.title.background\": background,\n        \"editor.hover.title.foreground\": foreground,\n        \"editor.hover.border\": borderColor,\n        \"editor.hover.contents.background\": background,\n        \"editor.hover.contents.foreground\": foreground,\n\n        \"sidebar.background\": shellBackground,\n        \"sidebar.foreground\": foreground,\n        \"sidebar.active.background\": background,\n        \"sidebar.selection.border\": borderColor,\n\n        \"tabs.background\": background,\n        \"tabs.foreground\": foreground,\n        \"tabs.active.background\": null,\n        \"tabs.active.foreground\": null,\n\n        \"scrollbar.track\": null,\n        \"scrollbar.thumb\": null,\n        \"scrollbar.thumb.hover\": null,\n\n        \"title.background\": shellBackground,\n        \"title.foreground\": foreground,\n\n        // Context menu is used for completion, refactoring\n        \"contextMenu.background\": background,\n        \"contextMenu.foreground\": foreground,\n        \"contextMenu.border\": borderColor,\n        \"contextMenu.highlight\": borderColor,\n\n        // Menu is used for the popup menu\n        \"menu.background\": background,\n        \"menu.foreground\": foreground,\n        \"menu.border\": borderColor,\n    }\n}\n\nconst ColorBlack = (PersistentSettings.get(\"_internal.lastBackgroundColor\") as string) || \"#1E2127\"\nconst ColorWhite = \"white\"\n\nconst InsertMode = \"#00c864\"\nconst OperatorMode = \"#ff6400\"\nconst NormalMode = \"#0064ff\"\n\nconst HighlightForeground = \"#dcdcdc\"\n\nconst StatusBarBackground = \"#282828\"\nconst StatusBarForeground = \"#c8c8c8\"\n\nexport const DefaultThemeColors: IThemeColors = {\n    background: ColorBlack,\n    foreground: ColorWhite,\n\n    \"editor.background\": ColorBlack,\n    \"editor.foreground\": ColorWhite,\n\n    \"title.background\": ColorBlack,\n    \"title.foreground\": ColorWhite,\n\n    \"highlight.mode.insert.foreground\": HighlightForeground,\n    \"highlight.mode.insert.background\": InsertMode,\n\n    \"highlight.mode.normal.foreground\": HighlightForeground,\n    \"highlight.mode.normal.background\": NormalMode,\n\n    \"highlight.mode.visual.foreground\": HighlightForeground,\n    \"highlight.mode.visual.background\": NormalMode,\n\n    \"highlight.mode.operator.foreground\": HighlightForeground,\n    \"highlight.mode.operator.background\": OperatorMode,\n\n    // Tool tip is used for some contextual information,\n    // like hover, as well as for rename.\n    \"toolTip.background\": ColorBlack,\n    \"toolTip.foreground\": ColorWhite,\n    \"toolTip.border\": ColorWhite,\n\n    \"editor.hover.title.background\": ColorBlack,\n    \"editor.hover.title.foreground\": ColorWhite,\n    \"editor.hover.border\": ColorWhite,\n    \"editor.hover.contents.background\": ColorBlack,\n    \"editor.hover.contents.foreground\": ColorWhite,\n    \"editor.hover.contents.codeblock.background\": ColorBlack,\n    \"editor.hover.contents.codeblock.foreground\": ColorWhite,\n\n    // Context menu is used for completion, refactoring\n    \"contextMenu.background\": ColorBlack,\n    \"contextMenu.foreground\": ColorBlack,\n    \"contextMenu.border\": ColorWhite,\n    \"contextMenu.highlight\": ColorBlack,\n\n    // Menu is used for the popup menu\n    \"menu.background\": ColorBlack,\n    \"menu.foreground\": ColorBlack,\n    \"menu.border\": ColorWhite,\n    \"menu.highlight\": ColorBlack,\n\n    \"statusBar.background\": StatusBarBackground,\n    \"statusBar.foreground\": StatusBarForeground,\n\n    \"sidebar.background\": ColorBlack,\n    \"sidebar.foreground\": ColorWhite,\n    \"sidebar.active.background\": ColorBlack,\n    \"sidebar.selection.border\": ColorWhite,\n\n    \"tabs.background\": ColorBlack,\n    \"tabs.foreground\": ColorWhite,\n    \"tabs.borderBottom\": null,\n    \"tabs.active.background\": null,\n    \"tabs.active.foreground\": null,\n\n    \"scrollbar.track\": null,\n    \"scrollbar.thumb\": null,\n    \"scrollbar.thumb.hover\": null,\n\n    \"fileExplorer.background\": StatusBarBackground,\n    \"fileExplorer.foreground\": StatusBarForeground,\n    \"fileExplorer.selection.background\": NormalMode,\n    \"fileExplorer.selection.foreground\": HighlightForeground,\n    \"fileExplorer.cursor.background\": NormalMode,\n    \"fileExplorer.cursor.foreground\": NormalMode,\n    \"editor.tokenColors\": [],\n}\n\n// Value used to determine whether the base Vim theme\n// should be set to 'dark' or 'light'\nexport type VimBackground = \"light\" | \"dark\"\n\nexport interface IThemeMetadata {\n    name: string\n    baseVimTheme?: string\n    baseVimBackground?: VimBackground\n    colors: Partial<IThemeColors>\n    tokenColors: TokenColor[]\n}\n\nexport const DefaultTheme: IThemeMetadata = {\n    name: \"default\",\n    baseVimTheme: \"default\",\n    colors: DefaultThemeColors,\n    tokenColors: [],\n}\n\nexport class ThemeManager {\n    private _onThemeChangedEvent: Event<void> = new Event<void>()\n\n    private _activeTheme: IThemeMetadata = DefaultTheme\n\n    private _isAnonymousTheme: boolean = false\n\n    // _colors stores the current theme colors mixed with configuration\n    private _colors: IThemeColors = DefaultThemeColors\n\n    public get activeTheme(): IThemeMetadata {\n        return this._activeTheme\n    }\n\n    constructor(private _themeLoader: IThemeLoader) {}\n\n    public async getAllThemes(): Promise<IThemeContribution[]> {\n        return this._themeLoader.getAllThemes()\n    }\n\n    public async setTheme(name: string): Promise<void> {\n        // TODO: Load theme...\n        if (!name || name === this._activeTheme.name) {\n            return\n        }\n\n        const theme = await this._themeLoader.getThemeByName(name)\n\n        if (!theme) {\n            // If we couldn't find the theme... we'll try\n            // loading vim-style, and derive a theme from\n            // that.\n            this._isAnonymousTheme = true\n\n            const temporaryVimTheme: IThemeMetadata = {\n                name,\n                baseVimTheme: name,\n                colors: DefaultThemeColors,\n                tokenColors: [],\n            }\n\n            this._updateTheme(temporaryVimTheme)\n        } else {\n            this._updateTheme(theme)\n        }\n    }\n\n    public async notifyVimThemeChanged(\n        vimName: string,\n        backgroundColor: string,\n        foregroundColor: string,\n    ): Promise<void> {\n        // If the vim colorscheme changed, for example, via `:co <sometheme>`,\n        // then we should update our theme to match\n        if (\n            this._isAnonymousTheme ||\n            (this._activeTheme.baseVimTheme &&\n                this._activeTheme.baseVimTheme !== vimName &&\n                this._activeTheme.baseVimTheme !== \"*\")\n        ) {\n            this._isAnonymousTheme = false\n\n            const vimTheme: IThemeMetadata = {\n                name: vimName,\n                baseVimTheme: vimName,\n                colors: getColorsFromBackgroundAndForeground(backgroundColor, foregroundColor),\n                tokenColors: [],\n            }\n\n            this._updateTheme(vimTheme)\n        }\n    }\n\n    public get onThemeChanged(): IEvent<void> {\n        return this._onThemeChangedEvent\n    }\n\n    public getColors(): IThemeColors {\n        return this._colors\n    }\n\n    private _updateTheme(theme: IThemeMetadata): void {\n        this._activeTheme = theme\n\n        const userColors = getColorsFromConfig({\n            config: configuration,\n            defaultTheme: DefaultThemeColors,\n            themeColors: this.activeTheme.colors,\n        })\n\n        this._colors = {\n            ...DefaultThemeColors,\n            ...this._activeTheme.colors,\n            ...userColors,\n        }\n\n        this._onThemeChangedEvent.dispatch()\n    }\n}\n\nlet _themeManager: ThemeManager = null\nexport const activateThemes = (pluginManager: PluginManager): void => {\n    const loader = new PluginThemeLoader(pluginManager)\n    _themeManager = new ThemeManager(loader)\n}\n\nexport const getThemeManagerInstance = () => {\n    return _themeManager\n}\n"
  },
  {
    "path": "browser/src/Services/Themes/ThemePicker.ts",
    "content": "/**\n * ThemePicker\n *\n * UI for showing available themes in a menu\n */\n\nimport { CallbackCommand, commandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { MenuManager } from \"./../Menu\"\nimport { ThemeManager } from \"./ThemeManager\"\n\nconst chooseTheme = async (\n    configuration: Configuration,\n    menuManager: MenuManager,\n    themeManager: ThemeManager,\n) => {\n    const themes = await themeManager.getAllThemes()\n\n    const items = themes.map(t => ({\n        icon: \"paint\",\n        label: t.name,\n        detail: t.path,\n    }))\n\n    const currentTheme = themeManager.activeTheme.name\n\n    const themeMenu = menuManager.create()\n    themeMenu.show()\n    themeMenu.setItems(items)\n\n    let wasSelected = false\n\n    themeMenu.onItemSelected.subscribe(() => (wasSelected = true))\n\n    themeMenu.onHide.subscribe(() => {\n        if (!wasSelected) {\n            themeManager.setTheme(currentTheme)\n        }\n    })\n\n    themeMenu.onSelectedItemChanged.subscribe(newOption => {\n        if (newOption) {\n            configuration.setValues({ \"ui.colorscheme\": newOption.label })\n            themeManager.setTheme(newOption.label)\n        } else {\n            themeManager.setTheme(currentTheme)\n        }\n    })\n}\n\nexport const activate = (\n    configuration: Configuration,\n    menuManager: MenuManager,\n    themeManager: ThemeManager,\n) => {\n    commandManager.registerCommand(\n        new CallbackCommand(\n            \"oni.themes.choose\",\n            \"Themes: Choose Theme\",\n            \"Choose your theme from the available bundled themes.\",\n            () => chooseTheme(configuration, menuManager, themeManager),\n        ),\n    )\n}\n"
  },
  {
    "path": "browser/src/Services/Themes/index.ts",
    "content": "export * from \"./ThemeLoader\"\nexport * from \"./ThemeManager\"\n\nimport { PluginManager } from \"./../../Plugins/PluginManager\"\n\nimport { Configuration, IConfigurationValues } from \"./../Configuration\"\nimport { activateThemes, getThemeManagerInstance } from \"./ThemeManager\"\n\nexport const activate = async (\n    configuration: Configuration,\n    pluginManager: PluginManager,\n): Promise<void> => {\n    activateThemes(pluginManager)\n\n    const updateColorScheme = async (\n        configurationValues: Partial<IConfigurationValues>,\n    ): Promise<void> => {\n        const colorscheme = configurationValues[\"ui.colorscheme\"]\n        if (colorscheme) {\n            const themeManager = getThemeManagerInstance()\n            await themeManager.setTheme(colorscheme)\n        }\n    }\n\n    configuration.onConfigurationChanged.subscribe((newValues: Partial<IConfigurationValues>) => {\n        updateColorScheme(newValues)\n    })\n\n    await updateColorScheme(configuration.getValues())\n}\n"
  },
  {
    "path": "browser/src/Services/TokenColors.ts",
    "content": "/**\n * TokenColors\n *\n * - Rationalizes colors from both the active theme and configuration\n * - The 'source of truth' for tokenColors in Oni\n * - Also will handle 'fallback logic' for tokenColors\n */\n\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { Configuration, IConfigurationValues } from \"./Configuration\"\nimport { ThemeManager } from \"./Themes\"\n\nexport interface TokenColor {\n    scope: string[]\n    settings: TokenColorStyle\n    // private field for determining where a token came from\n    _source?: string\n}\n\nexport interface ThemeToken {\n    scope: string | string[]\n    settings: TokenColorStyle\n    _source?: string\n}\n\nexport interface TokenColorStyle {\n    foreground: string\n    background: string\n\n    fontStyle: \"bold\" | \"italic\" | \"bold italic\"\n}\n\nexport class TokenColors implements IDisposable {\n    private _subscriptions: IDisposable[] = []\n    private _tokenColors: TokenColor[] = []\n    private _onTokenColorsChangedEvent: Event<void> = new Event<void>()\n\n    private _defaultTokenColors: TokenColor[] = []\n\n    public get tokenColors(): TokenColor[] {\n        return this._tokenColors\n    }\n\n    public get onTokenColorsChanged(): IEvent<void> {\n        return this._onTokenColorsChangedEvent\n    }\n\n    constructor(private _configuration: Configuration, private _themeManager: ThemeManager) {\n        const sub1 = this._themeManager.onThemeChanged.subscribe(() => {\n            this._updateTokenColors()\n        })\n\n        const sub2 = this._configuration.onConfigurationChanged.subscribe(\n            (newValues: Partial<IConfigurationValues>) => {\n                if (newValues[\"editor.tokenColors\"]) {\n                    this._updateTokenColors()\n                }\n            },\n        )\n\n        this._subscriptions = [sub1, sub2]\n    }\n\n    public setDefaultTokenColors(tokenColors: TokenColor[]): void {\n        this._defaultTokenColors = tokenColors || []\n        this._updateTokenColors()\n    }\n\n    public dispose(): void {\n        this._subscriptions.forEach(s => s.dispose())\n        this._subscriptions = []\n    }\n\n    private _updateTokenColors(): void {\n        const {\n            activeTheme: {\n                colors: { \"editor.tokenColors\": themeTokens = [] },\n            },\n        } = this._themeManager\n\n        const userColors = this._configuration.getValue(\"editor.tokenColors\")\n\n        const combinedColors = this._mergeTokenColors({\n            user: userColors,\n            theme: themeTokens,\n            defaults: this._defaultTokenColors,\n        })\n\n        this._tokenColors = this._convertThemeTokenScopes(combinedColors)\n\n        this._onTokenColorsChangedEvent.dispatch()\n    }\n\n    /**\n     * Theme tokens can pass in token scopes as a string or an array\n     * this converts all token scopes passed in to an array of strings\n     *\n     * @name convertThemeTokenScopes\n     * @function\n     * @param {ThemeToken[]} tokens\n     * @returns {TokenColor[]}\n     */\n    private _convertThemeTokenScopes(tokens: ThemeToken[]) {\n        // TODO: figure out how space separated token scopes should be handled\n        // token.scope.split(\" \") -> convert \"meta.var string.quoted\" -> [\"meta.var\", \"string.quoted\"]\n        // this however breaks prioritisation of tokens\n        return tokens.map(token => {\n            const scope = !token.scope\n                ? []\n                : Array.isArray(token.scope)\n                    ? token.scope\n                    : [token.scope]\n            return { ...token, scope }\n        })\n    }\n\n    /**\n     * Merge different token source whilst unifying settings\n     * each source is passed by name so that later the priority\n     * for merging can be used e.g. if user source has a\n     * a higher priority then conflicting settings can prefer the\n     * user source\n     */\n    private _mergeTokenColors(tokens: {\n        user: ThemeToken[]\n        defaults: TokenColor[]\n        theme: ThemeToken[]\n    }) {\n        return Object.entries(tokens).reduce<ThemeToken[]>(\n            (output, [_source, tokenColors]) =>\n                tokenColors.reduce((mergedTokens, currentToken) => {\n                    const duplicateToken = mergedTokens.find(t => currentToken.scope === t.scope)\n                    if (duplicateToken) {\n                        return mergedTokens.map(existingToken => {\n                            if (existingToken.scope === duplicateToken.scope) {\n                                return this._mergeSettings(existingToken, {\n                                    ...currentToken,\n                                    _source,\n                                })\n                            }\n                            return existingToken\n                        })\n                    }\n                    return [...mergedTokens, { ...currentToken, _source }]\n                }, output),\n            [],\n        )\n    }\n\n    private _mergeSettings(prev: ThemeToken, next: ThemeToken) {\n        const priority = {\n            user: 2,\n            theme: 1,\n            defaults: 0,\n        }\n\n        if (priority[next._source] > priority[prev._source]) {\n            return {\n                ...next,\n                settings: {\n                    ...prev.settings,\n                    ...next.settings,\n                },\n            }\n        }\n        return {\n            ...prev,\n            settings: {\n                ...next.settings,\n                ...prev.settings,\n            },\n        }\n    }\n}\n\nlet _tokenColors: TokenColors\nexport const activate = (configuration: Configuration, themeManager: ThemeManager) => {\n    _tokenColors = new TokenColors(configuration, themeManager)\n}\n\nexport const getInstance = () => {\n    return _tokenColors\n}\n"
  },
  {
    "path": "browser/src/Services/TypingPredictionManager.ts",
    "content": "/**\n * TypingPredictionManager\n *\n * Handles typing-prediction state management\n */\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { IScreen } from \"./../neovim\"\n\nexport interface IPredictedCharacter {\n    character: string\n    id: number\n}\n\nexport interface ITypingPrediction {\n    predictedCharacters: IPredictedCharacter[]\n    predictedCursorColumn: number\n    backgroundColor: string\n    foregroundColor: string\n}\n\nexport class TypingPredictionManager {\n    private _predictionsChanged: Event<ITypingPrediction> = new Event<ITypingPrediction>()\n    private _predictions: IPredictedCharacter[] = []\n    private _backgroundColor: string\n    private _foregroundColor: string\n\n    private _enabled: boolean = false\n\n    private _line: number = null\n    private _column: number = null\n\n    private _latestScreenState: IScreen = null\n\n    public get onPredictionsChanged(): IEvent<ITypingPrediction> {\n        return this._predictionsChanged\n    }\n\n    public enable(): void {\n        this._enabled = true\n    }\n\n    public disable(): void {\n        this._enabled = false\n    }\n\n    public setCursorPosition(screen: IScreen): void {\n        this._latestScreenState = screen\n\n        const line = screen.cursorRow\n        const column = screen.cursorColumn\n\n        const { foregroundColor, backgroundColor } = getLastTextColorFromScreen(screen)\n\n        this._foregroundColor = foregroundColor\n        this._backgroundColor = backgroundColor\n\n        let shouldClearAll = false\n\n        // If we changed lines, our predictions are no longer valid\n        if (this._line !== line) {\n            shouldClearAll = true\n        }\n\n        // In the case where auto-indent pushes us back,\n        // we don't have a good sense of current predictions,\n        // so just clear them all out\n        if (column < this._column) {\n            shouldClearAll = true\n        }\n\n        this._line = line\n        this._column = column\n\n        if (shouldClearAll) {\n            this.clearAllPredictions()\n        } else {\n            this._predictions = this._predictions.filter(pd => {\n                return pd.id > this._column\n            })\n\n            this._notifyPredictionsChanged()\n        }\n    }\n\n    public addPrediction(character: string): void {\n        if (!this._enabled || !this._latestScreenState) {\n            return null\n        }\n\n        const id = this._column + this._predictions.length + 1\n\n        const newCharacterCell = this._latestScreenState.getCell(id, this._line)\n\n        if (newCharacterCell && newCharacterCell.character) {\n            return\n        }\n\n        this._predictions = [...this._predictions, { id, character }]\n\n        this._notifyPredictionsChanged()\n    }\n\n    public clearAllPredictions(): void {\n        this._predictions = []\n\n        this._notifyPredictionsChanged()\n    }\n\n    private _notifyPredictionsChanged(): void {\n        this._predictionsChanged.dispatch({\n            predictedCharacters: this._predictions,\n            predictedCursorColumn: this._column + this._predictions.length,\n            backgroundColor: this._backgroundColor,\n            foregroundColor: this._foregroundColor,\n        })\n    }\n}\n\nexport const getLastTextColorFromScreen = (\n    screen: IScreen,\n): { foregroundColor: string; backgroundColor: string } => {\n    const previousCharacterColumn = screen.cursorColumn - 2\n\n    if (previousCharacterColumn <= 0) {\n        return {\n            foregroundColor: screen.foregroundColor,\n            backgroundColor: screen.backgroundColor,\n        }\n    }\n\n    const previousCharacter = screen.getCell(previousCharacterColumn, screen.cursorRow)\n\n    if (previousCharacter.character) {\n        return {\n            foregroundColor: previousCharacter.foregroundColor || screen.foregroundColor,\n            backgroundColor: previousCharacter.backgroundColor || screen.backgroundColor,\n        }\n    } else {\n        return {\n            foregroundColor: screen.foregroundColor,\n            backgroundColor: screen.backgroundColor,\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/UnhandledErrorMonitor.ts",
    "content": "/**\n * UnhandledErrorMonitor\n *\n * Helper module to listen to unhandled errors\n */\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { Configuration } from \"./Configuration\"\nimport { Notifications } from \"./Notifications\"\n\nimport * as Log from \"oni-core-logging\"\n\nexport class UnhandledErrorMonitor {\n    private _onUnhandledErrorEvent = new Event<Error>()\n    private _onUnhandledRejectionEvent = new Event<string>()\n\n    private _queuedErrors: Error[] = []\n    private _queuedRejections: string[] = []\n    private _started: boolean = false\n\n    public get onUnhandledError(): IEvent<Error> {\n        return this._onUnhandledErrorEvent\n    }\n\n    public get onUnhandledRejection(): IEvent<string> {\n        return this._onUnhandledRejectionEvent\n    }\n\n    constructor() {\n        window.addEventListener(\"unhandledrejection\", (evt: any) => {\n            if (!this._started) {\n                this._queuedRejections.push(evt.reason)\n            }\n\n            this._onUnhandledRejectionEvent.dispatch(evt.reason)\n        })\n\n        window.addEventListener(\"error\", (evt: ErrorEvent) => {\n            if (!this._started) {\n                const hasOccured = this._queuedErrors.find(\n                    e => evt.error && e.name && e.name === evt.error.name,\n                )\n                if (!hasOccured) {\n                    this._queuedErrors.push(evt.error)\n                }\n            }\n\n            this._onUnhandledErrorEvent.dispatch(evt.error)\n        })\n    }\n\n    public start(): void {\n        this._started = true\n\n        this._queuedRejections.forEach(rejection =>\n            this._onUnhandledRejectionEvent.dispatch(rejection),\n        )\n        this._queuedErrors.forEach(err => this._onUnhandledErrorEvent.dispatch(err))\n\n        this._queuedErrors = []\n        this._queuedRejections = []\n    }\n}\n\nlet _unhandledErrorMonitor: UnhandledErrorMonitor = null\n\nexport const activate = () => {\n    if (!_unhandledErrorMonitor) {\n        _unhandledErrorMonitor = new UnhandledErrorMonitor()\n    }\n}\n\nimport { remote } from \"electron\"\n\nexport const start = (configuration: Configuration, notifications: Notifications) => {\n    const showError = (title: string, errorText: string) => {\n        if (!configuration.getValue(\"debug.showNotificationOnError\")) {\n            Log.error(\"Received notification for - \" + title + \":\" + errorText)\n            return\n        }\n\n        const notification = notifications.createItem()\n\n        notification.onClick.subscribe(() => {\n            remote.getCurrentWebContents().openDevTools()\n        })\n\n        notification.setLevel(\"error\")\n        notification.setContents(title, errorText)\n        notification.show()\n    }\n\n    _unhandledErrorMonitor.onUnhandledError.subscribe(val => {\n        const errorText = val ? val.toString() : \"Open the debugger for more details.\"\n        showError(\n            \"Unhandled Exception\",\n            errorText +\n                `\\nPlease report this error. ${val && val.stack ? `Callstack:` + val.stack : \"\"}`,\n        )\n    })\n\n    _unhandledErrorMonitor.onUnhandledRejection.subscribe(val => {\n        const errorText: string = val ? val.toString() : \"Open the debugger for more details.\"\n        showError(\"Unhandled Rejection\", errorText + \"\\nPlease report this error.\")\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/VersionControl/VersionControlBlameLayer.tsx",
    "content": "import { pathExists } from \"fs-extra\"\nimport { Buffer, BufferLayer, Commands, Configuration } from \"oni-api\"\nimport { warn } from \"oni-core-logging\"\nimport * as React from \"react\"\nimport { Transition } from \"react-transition-group\"\nimport { Position } from \"vscode-languageserver-types\"\n\nimport { LayerContextWithCursor } from \"../../Editor/NeovimEditor/NeovimBufferLayersView\"\nimport styled, { pixel, textOverflow, withProps } from \"../../UI/components/common\"\nimport { getTimeSince } from \"../../Utility\"\nimport { VersionControlProvider } from \"./\"\nimport { Blame as IBlame } from \"./VersionControlProvider\"\n\ntype TransitionStates = \"entering\" | \"entered\" | \"exiting\"\n\ninterface IBlamePosition {\n    top: number\n    left: number\n    hide: boolean\n}\n\ninterface ICanFit {\n    canFit: boolean\n    message: string\n    position: IBlamePosition\n}\n\ninterface ILineDetails {\n    nextSpacing: number\n    lastEmptyLine: number\n}\n\nexport interface IProps extends LayerContextWithCursor {\n    getBlame: (lineOne: number, lineTwo: number) => Promise<IBlame>\n    timeout: number\n    cursorScreenLine: number\n    cursorBufferLine: number\n    currentLine: string\n    mode: \"auto\" | \"manual\"\n    fontFamily: string\n    setupCommand: (callback: () => void) => void\n}\n\nexport interface IState {\n    blame: IBlame\n    showBlame: boolean\n    currentLineContent: string\n    currentCursorBufferLine: number\n    error: Error\n}\n\ninterface IContainerProps {\n    height: number\n    top: number\n    left: number\n    fontFamily: string\n    hide: boolean\n    timeout: number\n    animationState: TransitionStates\n}\n\nconst getOpacity = (state: TransitionStates) => {\n    const transitionStyles = {\n        entering: 0,\n        entered: 0.5,\n        exiting: 0,\n    }\n    return transitionStyles[state]\n}\n\nexport const BlameContainer = withProps<IContainerProps>(styled.div).attrs({\n    style: ({ top, left }: IContainerProps) => ({\n        top: pixel(top),\n        left: pixel(left),\n    }),\n})`\n    ${p => p.hide && `visibility: hidden`};\n    width: auto;\n    box-sizing: border-box;\n    position: absolute;\n    font-style: italic;\n    font-family: ${p => p.fontFamily};\n    color: ${p => p.theme[\"menu.foreground\"]};\n    opacity: ${p => getOpacity(p.animationState)};\n    transition: opacity ${p => p.timeout}ms ease-in-out;\n    height: ${p => pixel(p.height)};\n    line-height: ${p => pixel(p.height)};\n    right: 3em;\n    ${textOverflow}\n`\n\nconst BlameDetails = styled.span`\n    color: inherit;\n    width: 100%;\n`\n\n// CurrentLine - the string in the current line\n// CursorLine - The 0 based position of the cursor in the file i.e. at line 30 this will be 29\n// CursorBufferLine - The 1 based position of the cursor in the file i.e. at line 30 it will be 30\n// CursorScreenLine - the position of the cursor within the visible lines so if line 30 is at the\n// top of the viewport it will be 0\n\nexport class Blame extends React.PureComponent<IProps, IState> {\n    // Reset show blame to false when props change - do it here so it happens before rendering\n    // hide if the current line has changed or if the text of the line has changed\n    // aka input is in progress or if there is an empty line\n    public static getDerivedStateFromProps(nextProps: IProps, prevState: IState) {\n        const lineNumberChanged = nextProps.cursorBufferLine !== prevState.currentCursorBufferLine\n        const lineContentChanged = prevState.currentLineContent !== nextProps.currentLine\n        if (\n            (prevState.showBlame && (lineNumberChanged || lineContentChanged)) ||\n            !nextProps.currentLine\n        ) {\n            return {\n                showBlame: false,\n                blame: prevState.blame,\n                currentLineContent: nextProps.currentLine,\n                currentCursorBufferLine: nextProps.cursorBufferLine,\n            }\n        }\n        return null\n    }\n\n    public state: IState = {\n        error: null,\n        blame: null,\n        showBlame: null,\n        currentLineContent: this.props.currentLine,\n        currentCursorBufferLine: this.props.cursorBufferLine,\n    }\n\n    private _timeout: any\n    private readonly DURATION = 300\n    private readonly LEFT_OFFSET = 4\n\n    public async componentDidMount() {\n        const { cursorBufferLine, mode } = this.props\n        await this.updateBlame(cursorBufferLine, cursorBufferLine)\n        if (mode === \"auto\") {\n            this.resetTimer()\n        }\n        this.props.setupCommand(() => {\n            const { showBlame } = this.state\n            this.setState({ showBlame: !showBlame })\n        })\n    }\n\n    public async componentDidUpdate(prevProps: IProps, prevState: IState) {\n        const { cursorBufferLine, currentLine, mode } = this.props\n        if (prevProps.cursorBufferLine !== cursorBufferLine && currentLine) {\n            await this.updateBlame(cursorBufferLine, cursorBufferLine)\n            if (mode === \"auto\") {\n                return this.resetTimer()\n            }\n        }\n    }\n\n    public componentWillUnmount() {\n        clearTimeout(this._timeout)\n    }\n\n    public componentDidCatch(error: Error) {\n        warn(`Oni VCS Blame layer failed because: ${error.message}`)\n        this.setState({ error })\n    }\n\n    public resetTimer = () => {\n        clearTimeout(this._timeout)\n        this._timeout = setTimeout(() => {\n            if (this.props.currentLine) {\n                this.setState({ showBlame: true })\n            }\n        }, this.props.timeout)\n    }\n\n    public getLastEmptyLine() {\n        const { cursorLine, visibleLines, topBufferLine } = this.props\n        const lineDetails: ILineDetails = {\n            lastEmptyLine: null,\n            nextSpacing: null,\n        }\n        for (\n            let currentBufferLine = cursorLine;\n            currentBufferLine >= topBufferLine;\n            currentBufferLine--\n        ) {\n            const screenLine = currentBufferLine - topBufferLine\n            const line = visibleLines[screenLine]\n            if (!line.length) {\n                const nextLine = visibleLines[screenLine + 1]\n                lineDetails.lastEmptyLine = currentBufferLine\n                // search for index of first non-whitespace character which is equivalent\n                // to the whitespace count\n                lineDetails.nextSpacing = nextLine.search(/\\S/)\n                break\n            }\n        }\n        return lineDetails\n    }\n\n    public calculatePosition(canFit: boolean) {\n        const { cursorLine, cursorScreenLine, visibleLines } = this.props\n        const currentLine = visibleLines[cursorScreenLine]\n        const character = currentLine && currentLine.length + this.LEFT_OFFSET\n\n        if (canFit) {\n            return this.getPosition({ line: cursorLine, character })\n        }\n\n        const { lastEmptyLine, nextSpacing } = this.getLastEmptyLine()\n\n        if (lastEmptyLine) {\n            return this.getPosition({ line: lastEmptyLine - 1, character: nextSpacing })\n        }\n\n        return this.getPosition()\n    }\n\n    // TODO: possibly add a caching strategy so a new call isn't made each time or\n    // get a blame for the entire file and store it\n    public updateBlame = async (lineOne: number, lineTwo: number) => {\n        const outOfBounds = this.isOutOfBounds(lineOne, lineTwo)\n        const blame = !outOfBounds ? await this.props.getBlame(lineOne, lineTwo) : null\n        this.setState({ blame })\n    }\n\n    public formatCommitDate(timestamp: string) {\n        return new Date(parseInt(timestamp, 10) * 1000)\n    }\n\n    public getPosition(positionToRender?: Position): IBlamePosition {\n        const emptyPosition: IBlamePosition = {\n            hide: true,\n            top: null,\n            left: null,\n        }\n        if (!positionToRender) {\n            return emptyPosition\n        }\n        const position = this.props.bufferToPixel(positionToRender)\n        if (!position) {\n            return emptyPosition\n        }\n        return {\n            hide: false,\n            top: position.pixelY,\n            left: position.pixelX,\n        }\n    }\n\n    public isOutOfBounds = (...lines: number[]) => {\n        return lines.some(\n            line => !line || line > this.props.bottomBufferLine || line < this.props.topBufferLine,\n        )\n    }\n\n    public getBlameText = (numberOfTruncations = 0) => {\n        const { blame } = this.state\n        if (!blame) {\n            return null\n        }\n        const { author, hash, committer_time } = blame\n        const formattedDate = this.formatCommitDate(committer_time)\n        const timeSince = `${getTimeSince(formattedDate)} ago`\n        const formattedHash = hash.slice(0, 4).toUpperCase()\n\n        const words = blame.summary.split(\" \")\n        const message = words.slice(0, words.length - numberOfTruncations).join(\" \")\n\n        const symbol = \"…\"\n        const summary = numberOfTruncations && words.length > 2 ? message.concat(symbol) : message\n\n        return words.length < 2\n            ? `${author}, ${timeSince}`\n            : `${author}, ${timeSince}, ${summary} #${formattedHash}`\n    }\n\n    // Recursively calls get blame text if the message will not fit onto the screen up\n    // to a limit of 6 times each time removing one word from the blame message\n    // if after 6 attempts the message is still not small enougth then we render the popup\n    public canFit = (truncationAmount = 0): ICanFit => {\n        const { visibleLines, dimensions, cursorScreenLine } = this.props\n        const message = this.getBlameText(truncationAmount)\n        const currentLine = visibleLines[cursorScreenLine] || \"\"\n        const canFit = dimensions.width > currentLine.length + message.length + this.LEFT_OFFSET\n\n        if (!canFit && truncationAmount <= 6) {\n            return this.canFit(truncationAmount + 1)\n        }\n        const truncatedOrFullMessage = canFit ? message : this.getBlameText()\n        return {\n            canFit,\n            message: truncatedOrFullMessage,\n            position: this.calculatePosition(canFit),\n        }\n    }\n\n    public render() {\n        const { blame, showBlame, error } = this.state\n        if (!blame || !showBlame || error) {\n            return null\n        }\n        const { message, position } = this.canFit()\n        return (\n            <Transition in={blame && showBlame} timeout={this.DURATION}>\n                {(state: TransitionStates) => (\n                    <BlameContainer\n                        {...position}\n                        data-id=\"vcs.blame\"\n                        timeout={this.DURATION}\n                        animationState={state}\n                        height={this.props.fontPixelHeight}\n                        fontFamily={this.props.fontFamily}\n                    >\n                        <BlameDetails>{message}</BlameDetails>\n                    </BlameContainer>\n                )}\n            </Transition>\n        )\n    }\n}\n\nexport default class VersionControlBlameLayer implements BufferLayer {\n    constructor(\n        private _buffer: Buffer,\n        private _vcsProvider: VersionControlProvider,\n        private _configuration: Configuration,\n        private _commands: Commands.Api,\n    ) {}\n\n    public getBlame = async (lineOne: number, lineTwo: number) => {\n        const fileExists = await pathExists(this._buffer.filePath)\n        return (\n            fileExists &&\n            this._vcsProvider.getBlame({ file: this._buffer.filePath, lineOne, lineTwo })\n        )\n    }\n\n    get id() {\n        return \"vcs.blame\"\n    }\n\n    public setupCommand = (callback: () => void) => {\n        this._commands.registerCommand({\n            command: \"experimental.vcs.blame.toggleBlame\",\n            name: null,\n            detail: null,\n            enabled: this._isActive,\n            execute: callback,\n        })\n    }\n\n    public getConfigOpts() {\n        const fontFamily = this._configuration.getValue<string>(\"editor.fontFamily\")\n        const timeout = this._configuration.getValue<number>(\"experimental.vcs.blame.timeout\")\n        const mode = this._configuration.getValue<\"auto\" | \"manual\">(\"experimental.vcs.blame.mode\")\n\n        return { timeout, mode, fontFamily }\n    }\n\n    public render(context: LayerContextWithCursor) {\n        const cursorBufferLine = context.cursorLine + 1\n        const cursorScreenLine = cursorBufferLine - context.topBufferLine\n        const config = this.getConfigOpts()\n        const activated = this._isActive()\n        return (\n            activated && (\n                <Blame\n                    {...context}\n                    mode={config.mode}\n                    timeout={config.timeout}\n                    getBlame={this.getBlame}\n                    fontFamily={config.fontFamily}\n                    setupCommand={this.setupCommand}\n                    cursorBufferLine={cursorBufferLine}\n                    cursorScreenLine={cursorScreenLine}\n                    currentLine={context.visibleLines[cursorScreenLine]}\n                />\n            )\n        )\n    }\n\n    private _isActive() {\n        return this._vcsProvider && this._vcsProvider.isActivated\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/VersionControl/VersionControlManager.tsx",
    "content": "import { capitalize } from \"lodash\"\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { IDisposable } from \"oni-types\"\nimport * as React from \"react\"\n\nimport { store, SupportedProviders, VersionControlPane, VersionControlProvider } from \"./\"\nimport getBufferLayerInstance from \"./../../Editor/NeovimEditor/BufferLayerManager\"\nimport { Notifications } from \"./../../Services/Notifications\"\nimport { Branch } from \"./../../UI/components/VersionControl/Branch\"\nimport { SidebarManager } from \"./../Sidebar\"\nimport VersionControlBlameLayer from \"./VersionControlBlameLayer\"\n\ninterface ISendNotificationsArgs {\n    detail: string\n    level: \"info\" | \"warn\"\n    title: string\n    expiration?: number\n}\n\nexport type ISendVCSNotification = (args: ISendNotificationsArgs) => void\n\nexport class VersionControlManager {\n    private _vcs: SupportedProviders\n    private _vcsProvider: VersionControlProvider\n    private _menuInstance: Oni.Menu.MenuInstance\n    private _vcsStatusItem: Oni.StatusBarItem\n    private _subscriptions: IDisposable[] = []\n    private _providers = new Map<string, VersionControlProvider>()\n    private _bufferLayerManager = getBufferLayerInstance()\n\n    constructor(\n        private _oni: Oni.Plugin.Api,\n        private _sidebar: SidebarManager,\n        private _notifications: Notifications,\n    ) {}\n\n    public get providers() {\n        return this._providers\n    }\n\n    public get activeProvider(): VersionControlProvider {\n        return this._vcsProvider\n    }\n\n    public async registerProvider(provider: VersionControlProvider): Promise<void> {\n        if (provider) {\n            this._providers.set(provider.name, provider)\n            const canHandleWorkspace = await provider.canHandleWorkspace()\n            if (canHandleWorkspace) {\n                await this._activateVCSProvider(provider)\n            }\n\n            this._oni.workspace.onDirectoryChanged.subscribe(async dir => {\n                const providerToUse = await this.getCompatibleProvider(dir)\n                await this.handleProviderStatus(providerToUse)\n            })\n        }\n    }\n\n    // Use arrow function to maintain this binding of sendNotification\n    public sendNotification: ISendVCSNotification = ({ expiration = 3_000, ...args }) => {\n        const notification = this._notifications.createItem()\n        notification.setContents(args.title, args.detail)\n        notification.setExpiration(expiration)\n        notification.setLevel(args.level) // TODO: Integrate setLevel into API\n        notification.show()\n    }\n\n    public deactivateProvider(): void {\n        this._vcsProvider.deactivate()\n        this._subscriptions.map(s => s.dispose())\n        if (this._vcsStatusItem) {\n            this._vcsStatusItem.hide()\n        }\n        this._vcsProvider = null\n        this._vcs = null\n    }\n\n    public async handleProviderStatus(newProvider: VersionControlProvider): Promise<void> {\n        const isSameProvider = this._vcsProvider && newProvider && this._vcs === newProvider.name\n        const noCompatibleProvider = this._vcsProvider && !newProvider\n        const newReplacementProvider = Boolean(this._vcsProvider && newProvider)\n        const compatibleProvider = Boolean(!this._vcsProvider && newProvider)\n\n        switch (true) {\n            case isSameProvider:\n                break\n            case noCompatibleProvider:\n                this.deactivateProvider()\n                break\n            case newReplacementProvider:\n                this.deactivateProvider()\n                await this._activateVCSProvider(newProvider)\n                break\n            case compatibleProvider:\n                await this._activateVCSProvider(newProvider)\n                break\n            default:\n                break\n        }\n    }\n\n    private async getCompatibleProvider(dir: string): Promise<VersionControlProvider | null> {\n        const allCompatibleProviders: VersionControlProvider[] = []\n        for (const vcs of this._providers.values()) {\n            const isCompatible = await vcs.canHandleWorkspace(dir)\n            if (isCompatible) {\n                allCompatibleProviders.push(vcs)\n            }\n        }\n        // TODO: when we have multiple providers we will need logic to determine which to\n        // use if more than one is compatible\n        const [providerToUse] = allCompatibleProviders\n\n        return providerToUse\n    }\n\n    private _activateVCSProvider = async (provider: VersionControlProvider) => {\n        this._vcs = provider.name\n        this._vcsProvider = provider\n        await this._initialize()\n        provider.activate()\n    }\n\n    private async _initialize() {\n        try {\n            await this._updateBranchIndicator()\n            this._setupSubscriptions()\n\n            const hasVcsSidebar = this._oni.sidebar.entries.some(({ id }) => id.includes(\"vcs\"))\n            const enabled = this._oni.configuration.getValue(\"experimental.vcs.sidebar\")\n\n            if (!hasVcsSidebar && enabled) {\n                const vcsPane = new VersionControlPane(\n                    this._oni,\n                    this._vcsProvider,\n                    this.sendNotification,\n                    this._sidebar, // TODO: Refactor API\n                    store,\n                )\n                this._sidebar.add(\"code-fork\", vcsPane) // TODO: Refactor API\n            }\n            // TODO: this should only be active if this is a file under version control\n            this._bufferLayerManager.addBufferLayer(\n                buffer =>\n                    this._oni.configuration.getValue(\"experimental.vcs.blame.enabled\") &&\n                    !!buffer.filePath,\n                buf =>\n                    new VersionControlBlameLayer(\n                        buf,\n                        this._vcsProvider,\n                        this._oni.configuration,\n                        this._oni.commands,\n                    ),\n            )\n\n            this._registerCommands()\n        } catch (e) {\n            Log.warn(`Failed to initialise provider, because, ${e.message}`)\n        }\n    }\n\n    private _setupSubscriptions() {\n        this._subscriptions = [\n            this._oni.editors.activeEditor.onBufferEnter.subscribe(async () => {\n                await this._updateBranchIndicator()\n            }),\n            this._vcsProvider.onBranchChanged.subscribe(async newBranch => {\n                await this._updateBranchIndicator(newBranch)\n                await this._oni.editors.activeEditor.neovim.command(\"e!\")\n            }),\n            this._oni.editors.activeEditor.onBufferSaved.subscribe(async () => {\n                await this._updateBranchIndicator()\n            }),\n            (this._oni.workspace as any).onFocusGained.subscribe(async () => {\n                await this._updateBranchIndicator()\n            }),\n        ]\n    }\n\n    private _registerCommands = () => {\n        const toggleVCS = () => {\n            this._sidebar.toggleVisibilityById(\"oni.sidebar.vcs\") // TODO: Refactor API\n        }\n\n        this._oni.commands.registerCommand({\n            command: \"vcs.sidebar.toggle\",\n            name: \"Version Control: Toggle Visibility\",\n            detail: \"Toggles the vcs pane in the sidebar\",\n            execute: toggleVCS,\n            enabled: () => this._oni.configuration.getValue(\"experimental.vcs.sidebar\"),\n        })\n\n        this._oni.commands.registerCommand({\n            command: `vcs.fetch`,\n            name: \"Fetch the selected branch\",\n            detail: \"\",\n            execute: this._fetchBranch,\n        })\n\n        this._oni.commands.registerCommand({\n            command: `vcs.branches`,\n            name: `Local ${capitalize(this._vcs)} Branches`,\n            detail: \"Open a menu with a list of all local branches\",\n            execute: this._createBranchList,\n        })\n    }\n\n    private _updateBranchIndicator = async (branchName?: string) => {\n        if (!this._vcsProvider) {\n            return\n        } else if (!this._vcsStatusItem) {\n            const vcsId = `oni.status.${this._vcs}`\n            this._vcsStatusItem = this._oni.statusBar.createItem(1, vcsId)\n        }\n\n        try {\n            // FIXME: there is race condition on deactivation of the provider\n            const branch = await this._vcsProvider.getBranch()\n            const diff = await this._vcsProvider.getDiff()\n\n            if (!branch || !diff) {\n                return Log.warn(`The ${!branch ? \"branch name\" : \"diff\"} could not be found`)\n            } else if (!branch && !diff) {\n                return this._vcsStatusItem.hide()\n            }\n\n            this._vcsStatusItem.setContents(<Branch branch={branch} diff={diff} />)\n            this._vcsStatusItem.show()\n        } catch (e) {\n            this._notifyOfError(e)\n            return this._vcsStatusItem.hide()\n        }\n    }\n\n    private _createBranchList = async () => {\n        if (!this._vcsProvider) {\n            return\n        }\n\n        const [currentBranch, branches] = await Promise.all([\n            this._vcsProvider.getBranch(),\n            this._vcsProvider.getLocalBranches(),\n        ])\n\n        this._menuInstance = this._oni.menu.create()\n\n        if (!branches) {\n            return\n        }\n\n        const branchItems = branches.all.map(branch => ({\n            label: branch,\n            icon: \"code-fork\",\n            pinned: currentBranch === branch,\n        }))\n\n        this._menuInstance.show()\n        this._menuInstance.setItems(branchItems)\n\n        this._menuInstance.onItemSelected.subscribe(async menuItem => {\n            if (menuItem && menuItem.label) {\n                try {\n                    await this._vcsProvider.changeBranch(menuItem.label)\n                } catch (e) {\n                    this._notifyOfError(e)\n                }\n            }\n        })\n    }\n\n    private _notifyOfError(error: Error) {\n        const name = this._vcsProvider ? capitalize(this._vcs) : \"VCS\"\n        const errorMessage = error && error.message ? error.message : null\n        this.sendNotification({\n            title: `${capitalize(name)} Plugin Error:`,\n            detail: `${name} plugin encountered an error ${errorMessage}`,\n            level: \"warn\",\n        })\n    }\n\n    private _fetchBranch = async () => {\n        if (this._menuInstance.isOpen() && this._menuInstance.selectedItem) {\n            try {\n                await this._vcsProvider.fetchBranchFromRemote({\n                    currentDir: this._oni.workspace.activeWorkspace,\n                    branch: this._menuInstance.selectedItem.label,\n                })\n            } catch (e) {\n                this._notifyOfError(e)\n            }\n        }\n    }\n}\n\n// Shelter the instance from the global scope -> globals are evil.\nfunction init() {\n    let Provider: VersionControlManager\n\n    const Activate = (\n        oni: Oni.Plugin.Api,\n        sidebar: SidebarManager,\n        notifications: Notifications,\n    ): void => {\n        Provider = new VersionControlManager(oni, sidebar, notifications)\n    }\n\n    const GetInstance = () => {\n        return Provider\n    }\n\n    return {\n        activate: Activate,\n        getInstance: GetInstance,\n    }\n}\nexport const { activate, getInstance } = init()\n"
  },
  {
    "path": "browser/src/Services/VersionControl/VersionControlPane.tsx",
    "content": "import * as capitalize from \"lodash/capitalize\"\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport * as path from \"path\"\nimport * as React from \"react\"\nimport { Provider, Store } from \"react-redux\"\n\nimport { SidebarManager } from \"../Sidebar\"\nimport { VersionControlProvider, VersionControlView } from \"./\"\nimport { ISendVCSNotification } from \"./VersionControlManager\"\nimport { ProviderActions, VersionControlState } from \"./VersionControlStore\"\n\nexport interface IDsMap {\n    modified: \"modified\"\n    staged: \"staged\"\n    untracked: \"untracked\"\n    commits: \"commits\"\n    commitAll: \"commit_all\"\n}\n\nexport default class VersionControlPane {\n    public get id() {\n        return \"oni.sidebar.vcs\"\n    }\n\n    public get title() {\n        return capitalize(this._vcsProvider.name)\n    }\n\n    public readonly IDs: IDsMap = {\n        modified: \"modified\",\n        commits: \"commits\",\n        untracked: \"untracked\",\n        staged: \"staged\",\n        commitAll: \"commit_all\",\n    }\n\n    constructor(\n        private _oni: Oni.Plugin.Api,\n        private _vcsProvider: VersionControlProvider,\n        private _sendNotification: ISendVCSNotification,\n        private _sidebarManager: SidebarManager,\n        private _store: Store<VersionControlState>,\n    ) {\n        this._registerCommands()\n\n        this._oni.workspace.onDirectoryChanged.subscribe(this._refresh)\n        this._vcsProvider.onFileStatusChanged.subscribe(this._refresh)\n        this._vcsProvider.onBranchChanged.subscribe(this._getStatusIfVisible)\n        this._vcsProvider.onStagedFilesChanged.subscribe(this._getStatusIfVisible)\n        this._oni.editors.activeEditor.onBufferSaved.subscribe(this._getStatusIfVisible)\n        this._oni.editors.activeEditor.onBufferEnter.subscribe(this._getStatusIfVisible)\n\n        this._vcsProvider.onPluginActivated.subscribe(async () => {\n            this._store.dispatch({ type: \"ACTIVATE\" })\n            await this._refresh()\n        })\n\n        this._vcsProvider.onPluginDeactivated.subscribe(() => {\n            this._store.dispatch({ type: \"DEACTIVATE\" })\n        })\n    }\n\n    public async enter() {\n        this._store.dispatch({ type: \"ENTER\" })\n        await this._refresh()\n    }\n\n    public leave() {\n        this._store.dispatch({ type: \"LEAVE\" })\n    }\n\n    public getStatus = async () => {\n        const status = await this._vcsProvider.getStatus()\n        if (status) {\n            this._store.dispatch({ type: \"STATUS\", payload: { status } })\n        }\n        return status\n    }\n\n    public commit = async (messages: string[], files?: string[]) => {\n        let summary = null\n        const { status } = this._store.getState()\n        const filesToCommit = files || status.staged\n        this._dispatchLoading(true)\n        try {\n            summary = await this._vcsProvider.commitFiles(messages, filesToCommit)\n            this._store.dispatch({ type: \"COMMIT_SUCCESS\", payload: { commit: summary } })\n        } catch (e) {\n            this._sendNotification({\n                detail: e.message,\n                level: \"warn\",\n                title: `Error Commiting ${files[0]}`,\n            })\n            this._store.dispatch({ type: \"COMMIT_FAIL\" })\n        } finally {\n            await this._refresh()\n            this._dispatchLoading(false)\n        }\n    }\n\n    public stageFile = async (file: string) => {\n        try {\n            await this._vcsProvider.stageFile(file)\n        } catch (e) {\n            this._sendNotification({\n                detail: e.message,\n                level: \"warn\",\n                title: \"Error Staging File\",\n                expiration: 8_000,\n            })\n        }\n    }\n\n    public getLogs = async () => {\n        this._dispatchLoading(true)\n        const logs = await this._vcsProvider.getLogs()\n        if (logs) {\n            this._store.dispatch({ type: \"LOG\", payload: { logs } })\n            this._dispatchLoading(false)\n            return logs\n        }\n        return null\n    }\n\n    public uncommitFile = async (sha: string) => {\n        try {\n            await this._vcsProvider.uncommit()\n            await this._refresh()\n        } catch (error) {\n            this._sendNotification({\n                title: \"Unable to revert last commit\",\n                detail: error.message,\n                level: \"warn\",\n            })\n        }\n    }\n\n    public unstageFile = async () => {\n        const {\n            selected,\n            status: { staged },\n        } = this._store.getState()\n\n        if (!this._isReadonlyField(selected) && staged.includes(selected)) {\n            await this._vcsProvider.unstage([selected])\n        }\n    }\n\n    public setError = async (e: Error) => {\n        Log.warn(`version control pane failed to render due to ${e.message}`)\n        this._store.dispatch({ type: \"ERROR\" })\n    }\n\n    public updateSelection = (selected: string) => {\n        this._store.dispatch({ type: \"SELECT\", payload: { selected } })\n    }\n\n    public handleSelection = async (selected: string) => {\n        const { status, logs } = this._store.getState()\n        switch (true) {\n            case status.untracked.includes(selected):\n            case status.modified.includes(selected):\n                await this.stageFile(selected)\n                break\n            case logs && logs.latest && logs.latest.hash === selected:\n                await this.uncommitFile(selected)\n                break\n            case status.staged.includes(selected):\n                this._store.dispatch({ type: \"COMMIT_START\", payload: { files: [selected] } })\n                break\n            case selected === \"commit_all\" && !!status.staged.length:\n                this._store.dispatch({ type: \"COMMIT_START\", payload: { files: status.staged } })\n                break\n            default:\n                break\n        }\n    }\n\n    public render() {\n        return (\n            <Provider store={this._store}>\n                <VersionControlView\n                    IDs={this.IDs}\n                    commit={this.commit}\n                    setError={this.setError}\n                    getStatus={this.getStatus}\n                    handleSelection={this.handleSelection}\n                    updateSelection={this.updateSelection}\n                />\n            </Provider>\n        )\n    }\n\n    private _refresh = async () => {\n        await Promise.all([this.getStatus(), this.getLogs()])\n    }\n\n    private _getStatusIfVisible = async () => {\n        if (this._isVisible()) {\n            await this._refresh()\n        }\n    }\n\n    private _dispatchLoading = (loading: boolean, type: ProviderActions = \"commit\") => {\n        this._store.dispatch({ type: \"LOADING\", payload: { loading, type } })\n    }\n\n    private _isVisible = () =>\n        this._sidebarManager.isVisible && this._sidebarManager.activeEntryId === this.id\n\n    private _isReadonlyField = (field: string) => Object.values(this.IDs).includes(field)\n\n    private _toggleHelp = () => {\n        this._store.dispatch({ type: \"TOGGLE_HELP\" })\n    }\n\n    private _isCommiting = () => {\n        const state = this._store.getState()\n        return state.hasFocus && state.commit.active\n    }\n\n    private _hasFocus = () => {\n        const state = this._store.getState()\n        return state.hasFocus\n    }\n\n    private _getCurrentCommitMessage() {\n        const state = this._store.getState()\n        return state.commit.message\n    }\n\n    private _registerCommands() {\n        this._oni.commands.registerCommand({\n            command: \"vcs.commitAll\",\n            detail: \"Commit all staged files\",\n            name: \"Version Control: Commit all\",\n            enabled: this._isCommiting,\n            execute: async () => {\n                const currentMessage = this._getCurrentCommitMessage()\n                if (currentMessage.length) {\n                    await this.commit(currentMessage)\n                }\n            },\n        })\n\n        this._oni.commands.registerCommand({\n            command: \"vcs.openFile\",\n            detail: null,\n            name: null,\n            enabled: () => !this._isCommiting(),\n            execute: async () => {\n                const { selected } = this._store.getState()\n                if (!this._isReadonlyField(selected)) {\n                    const filePath = path.join(this._oni.workspace.activeWorkspace, selected)\n                    await this._oni.editors.openFile(filePath)\n                }\n            },\n        })\n\n        this._oni.commands.registerCommand({\n            command: \"vcs.refresh\",\n            detail: null,\n            name: null,\n            enabled: this._hasFocus,\n            execute: this._refresh,\n        })\n\n        this._oni.commands.registerCommand({\n            command: \"vcs.unstage\",\n            detail: null,\n            name: null,\n            enabled: () => this._hasFocus() && !this._isCommiting(),\n            execute: this.unstageFile,\n        })\n\n        this._oni.commands.registerCommand({\n            command: \"vcs.showHelp\",\n            detail: null,\n            name: null,\n            enabled: () => !this._isCommiting(),\n            execute: this._toggleHelp,\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/VersionControl/VersionControlProvider.ts",
    "content": "import { IEvent } from \"oni-types\"\nimport { BranchSummary, FetchResult } from \"simple-git/promise\"\n\nexport enum Statuses {\n    staged,\n    committed,\n    modified,\n}\n\nexport type FileStatusChangedEvent = Array<{\n    path: string\n    status: Statuses\n}>\n\nexport type BranchChangedEvent = string\nexport type StagedFilesChangedEvent = string\n\nexport interface StatusResult {\n    ahead: number\n    behind: number\n    currentBranch: string\n    modified: string[]\n    staged: string[]\n    conflicted: string[]\n    created: string[]\n    deleted: string[]\n    untracked: string[]\n    remoteTrackingBranch: string\n}\n\nexport interface BlameArgs {\n    lineOne: number\n    lineTwo: number\n    file: string\n}\n\nexport interface Blame {\n    author: string\n    author_mail: string\n    author_time: string\n    author_tz: string\n    committer: string\n    committer_mail: string\n    committer_time: string\n    committer_tz: string\n    filename: string\n    hash: string\n    line: { originalLine: string; finalLine: string; numberOfLines: string }\n    summary: string\n}\n\nexport interface VersionControlProvider {\n    // Events\n    onFileStatusChanged: IEvent<FileStatusChangedEvent>\n    onStagedFilesChanged: IEvent<StagedFilesChangedEvent>\n    onBranchChanged: IEvent<BranchChangedEvent>\n    onPluginActivated: IEvent<void>\n    onPluginDeactivated: IEvent<void>\n\n    name: SupportedProviders\n    isActivated: boolean\n    deactivate(): void\n    activate(): void\n    canHandleWorkspace(dir?: string): Promise<boolean>\n    getStatus(): Promise<StatusResult | void>\n    getRoot(): Promise<string | void>\n    getBlame(args: BlameArgs): Promise<Blame>\n    getDiff(): Promise<Diff | void>\n    getBranch(): Promise<string | void>\n    getLogs(file?: string): Promise<Logs>\n    getLocalBranches(): Promise<BranchSummary | void>\n    changeBranch(branch: string): Promise<void>\n    stageFile(file: string): Promise<void>\n    unstage(files: string[]): Promise<void>\n    uncommit(sha?: string): Promise<void>\n    commitFiles(message: string[], files?: string[]): Promise<Commits>\n    fetchBranchFromRemote(args: {\n        branch: string\n        origin?: string\n        currentDir: string\n    }): Promise<FetchResult>\n}\n\nexport interface DiffResultTextFile {\n    file: string\n    changes: number\n    insertions: number\n    deletions: number\n    binary: boolean\n}\n\nexport interface DiffResultBinaryFile {\n    file: string\n    before: number\n    after: number\n    binary: boolean\n}\n\nexport interface Diff {\n    files: Array<DiffResultTextFile | DiffResultBinaryFile>\n    insertions: number\n    deletions: number\n}\n\nexport interface Commits {\n    author: null | {\n        email: string\n        name: string\n    }\n    branch: string\n    commit: string\n    summary: {\n        changes: number\n        insertions: number\n        deletions: number\n    }\n}\n\nexport interface DefaultLogFields {\n    hash: string\n    date: string\n    message: string\n    author_name: string\n    author_email: string\n}\n\nexport interface ListLogSummary<T = DefaultLogFields> {\n    all: ReadonlyArray<T>\n    total: number\n    latest: T\n}\n\nexport type Logs = ListLogSummary<DefaultLogFields>\nexport type Summary = StatusResult\nexport type SupportedProviders = \"git\" | \"svn\"\nexport default VersionControlProvider\n"
  },
  {
    "path": "browser/src/Services/VersionControl/VersionControlStore.ts",
    "content": "import { createStore as createReduxStore } from \"./../../Redux\"\nimport { Commits, Logs, StatusResult } from \"./VersionControlProvider\"\n\nexport interface PrevCommits extends Commits {\n    message: string\n}\n\ninterface ICommit {\n    files: string[]\n    active: boolean\n    message: string[]\n    previousCommits: PrevCommits[]\n}\n\nexport type ProviderActions = \"commit\" | \"pull\" | \"fetch\" | \"stage\"\n\nexport interface VersionControlState {\n    loading: {\n        active: boolean\n        type: ProviderActions\n    }\n    selected: string\n    logs: Logs\n    status: StatusResult\n    commit: ICommit\n    hasFocus: boolean\n    hasError: boolean\n    activated: boolean\n    help: {\n        active: boolean\n    }\n}\n\ninterface IGenericAction<T, P = undefined> {\n    type: T\n    payload?: P\n}\n\nexport const DefaultState: VersionControlState = {\n    loading: {\n        active: false,\n        type: null,\n    },\n    selected: null,\n    logs: {\n        all: [],\n        total: null,\n        latest: null,\n    },\n    status: {\n        currentBranch: null,\n        staged: [],\n        conflicted: [],\n        created: [],\n        modified: [],\n        remoteTrackingBranch: null,\n        deleted: [],\n        untracked: [],\n        ahead: null,\n        behind: null,\n    },\n    commit: {\n        files: [],\n        message: [],\n        active: false,\n        previousCommits: [],\n    },\n    hasFocus: null,\n    activated: null,\n    hasError: false,\n    help: {\n        active: false,\n    },\n}\n\ntype ISelectAction = IGenericAction<\"SELECT\", { selected: string }>\ntype ILoadingAction = IGenericAction<\"LOADING\", { loading: boolean; type: ProviderActions }>\ntype IActivateAction = IGenericAction<\"ACTIVATE\">\ntype IDeactivateAction = IGenericAction<\"DEACTIVATE\">\ntype IToggleHelpAction = IGenericAction<\"TOGGLE_HELP\">\ntype IEnterAction = IGenericAction<\"ENTER\">\ntype ILeaveAction = IGenericAction<\"LEAVE\">\ntype IErrorAction = IGenericAction<\"ERROR\">\ntype IStatusAction = IGenericAction<\"STATUS\", { status: StatusResult }>\ntype ILogAction = IGenericAction<\"LOG\", { logs: Logs }>\ntype ICommitStartAction = IGenericAction<\"COMMIT_START\", { files: string[] }>\ntype ICommitCancelAction = IGenericAction<\"COMMIT_CANCEL\">\ntype ICommitSuccessAction = IGenericAction<\"COMMIT_SUCCESS\", { commit: Commits }>\ntype ICommitFailAction = IGenericAction<\"COMMIT_FAIL\">\ntype IUpdateCommitMessageAction = IGenericAction<\"UPDATE_COMMIT_MESSAGE\", { message: string[] }>\ntype IAction =\n    | ILoadingAction\n    | IToggleHelpAction\n    | ISelectAction\n    | IStatusAction\n    | ILogAction\n    | IEnterAction\n    | ILeaveAction\n    | IErrorAction\n    | IDeactivateAction\n    | IActivateAction\n    | ICommitStartAction\n    | ICommitCancelAction\n    | ICommitSuccessAction\n    | ICommitFailAction\n    | IUpdateCommitMessageAction\n\nexport interface IVersionControlActions {\n    cancelCommit: () => ICommitCancelAction\n    updateCommitMessage: (message: string[]) => IUpdateCommitMessageAction\n    setLoading: (isLoading: boolean) => ILoadingAction\n}\n\nexport const VersionControlActions: IVersionControlActions = {\n    setLoading: (isLoading: boolean, type = \"commit\") => ({\n        type: \"LOADING\",\n        payload: { loading: isLoading, type },\n    }),\n    cancelCommit: () => ({ type: \"COMMIT_CANCEL\" }),\n    updateCommitMessage: (message: string[]) => ({\n        type: \"UPDATE_COMMIT_MESSAGE\",\n        payload: { message },\n    }),\n}\n\nexport function reducer(state: VersionControlState, action: IAction) {\n    switch (action.type) {\n        case \"ENTER\":\n            return { ...state, hasFocus: true }\n        case \"LOADING\":\n            return {\n                ...state,\n                loading: {\n                    active: action.payload.loading,\n                    type: action.payload.type,\n                },\n            }\n        case \"SELECT\":\n            return { ...state, selected: action.payload.selected }\n        case \"COMMIT_START\":\n            return {\n                ...state,\n                commit: { ...state.commit, files: action.payload.files, active: true },\n            }\n        case \"COMMIT_CANCEL\":\n            return { ...state, commit: { ...state.commit, message: [], active: false, files: [] } }\n        case \"COMMIT_SUCCESS\":\n            const {\n                message: [message],\n            } = state.commit\n            return {\n                ...state,\n                loading: {\n                    active: false,\n                    type: null,\n                },\n                commit: {\n                    files: [],\n                    message: [] as string[],\n                    active: false,\n                    previousCommits: [\n                        ...state.commit.previousCommits,\n                        { ...action.payload.commit, message },\n                    ],\n                },\n            }\n        case \"COMMIT_FAIL\":\n            return {\n                ...state,\n                loading: {\n                    active: false,\n                    type: null,\n                },\n                commit: {\n                    ...state.commit,\n                    files: [],\n                    message: [],\n                    active: false,\n                },\n            }\n        case \"UPDATE_COMMIT_MESSAGE\":\n            return { ...state, commit: { ...state.commit, message: action.payload.message } }\n        case \"LEAVE\":\n            return { ...state, hasFocus: false }\n        case \"STATUS\":\n            return {\n                ...state,\n                status: action.payload.status,\n            }\n        case \"LOG\":\n            return {\n                ...state,\n                logs: action.payload.logs,\n            }\n        case \"DEACTIVATE\":\n            return {\n                ...state,\n                activated: false,\n                status: DefaultState.status,\n            }\n        case \"ACTIVATE\":\n            return {\n                ...state,\n                activated: true,\n            }\n        case \"ERROR\":\n            return {\n                ...state,\n                hasError: true,\n            }\n        case \"TOGGLE_HELP\":\n            return {\n                ...state,\n                help: {\n                    active: !state.help.active,\n                },\n            }\n        default:\n            return state\n    }\n}\n\nexport default createReduxStore(\"Version Control\", reducer, DefaultState)\n"
  },
  {
    "path": "browser/src/Services/VersionControl/VersionControlView.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport { styled } from \"./../../UI/components/common\"\nimport { SectionTitle, Title } from \"./../../UI/components/SectionTitle\"\nimport CommitsSection from \"./../../UI/components/VersionControl/Commits\"\nimport Help from \"./../../UI/components/VersionControl/Help\"\nimport StagedSection from \"./../../UI/components/VersionControl/Staged\"\nimport VersionControlStatus from \"./../../UI/components/VersionControl/Status\"\nimport { VimNavigator } from \"./../../UI/components/VimNavigator\"\nimport { IDsMap } from \"./VersionControlPane\"\nimport { Logs, StatusResult } from \"./VersionControlProvider\"\nimport {\n    PrevCommits,\n    ProviderActions,\n    VersionControlActions,\n    VersionControlState,\n} from \"./VersionControlStore\"\n\nconst StatusContainer = styled.div`\n    overflow-x: hidden;\n    overflow-y: auto;\n`\n\ninterface IStateProps {\n    loading: boolean\n    filesToCommit: string[]\n    loadingSection: ProviderActions\n    status: StatusResult\n    hasFocus: boolean\n    hasError: boolean\n    activated: boolean\n    committing: boolean\n    message: string[]\n    selectedItem: string\n    commits: PrevCommits[]\n    showHelp: boolean\n    logs: Logs\n}\n\ninterface IDispatchProps {\n    cancelCommit: () => void\n    updateCommitMessage: (message: string[]) => void\n    setLoading: (loading: boolean) => void\n}\n\ninterface IProps {\n    IDs: IDsMap\n    setError?: (e: Error) => void\n    commit?: (message: string[], files?: string[]) => Promise<void>\n    updateSelection?: (selection: string) => void\n    handleSelection?: (selection: string) => void\n    getStatus: () => void\n}\n\ntype ConnectedProps = IProps & IStateProps & IDispatchProps\n\ninterface State {\n    modified: boolean\n    staged: boolean\n    untracked: boolean\n    commits: boolean\n}\n\nexport class VersionControlView extends React.Component<ConnectedProps, State> {\n    public state: State = {\n        modified: true,\n        staged: true,\n        untracked: true,\n        commits: true,\n    }\n\n    public async componentDidMount() {\n        await this.props.getStatus()\n    }\n\n    public async componentDidCatch(e: Error) {\n        this.props.setError(e)\n    }\n\n    public toggleVisibility = (section: keyof State) => {\n        this.setState(prevState => ({ ...prevState, [section]: !prevState[section] }))\n    }\n\n    public toggleOrAction = (id: string) => {\n        const isSectionId = Object.keys(this.state).includes(id)\n        if (isSectionId) {\n            this.toggleVisibility(id as keyof State)\n        }\n        this.props.handleSelection(id)\n    }\n\n    public formatCommit = (message: string) => {\n        return message.length >= 50 ? [message.substr(0, 50), message.substr(50)] : [message]\n    }\n\n    public handleCommitMessage = (evt: React.ChangeEvent<HTMLInputElement>) => {\n        const { value } = evt.currentTarget\n        const message = this.formatCommit(value)\n        this.props.updateCommitMessage(message)\n    }\n\n    public handleCommitOne = async () => {\n        const { message, selectedItem } = this.props\n        await this.props.commit(message, [selectedItem])\n    }\n\n    public handleCommitAll = async () => {\n        const { message } = this.props\n        await this.props.commit(message)\n    }\n\n    public handleCommitCancel = () => {\n        this.props.cancelCommit()\n    }\n\n    public insertIf(condition: boolean, element: string[]) {\n        return condition ? element : []\n    }\n\n    public isSelected = (id: string) =>\n        this.props.committing &&\n        this.props.status.staged.length &&\n        this.state.staged &&\n        this.props.selectedItem === id\n\n    public getIds = () => {\n        const { logs, status, IDs } = this.props\n        const { modified, staged, untracked } = status\n        const commitSHAs = logs.all.slice(0, 1).map(({ hash }) => hash)\n        const ids = [\n            IDs.commits,\n            ...this.insertIf(this.state.commits, commitSHAs),\n            IDs.staged,\n            ...this.insertIf(this.state.staged && !!staged.length, [IDs.commitAll]),\n            ...this.insertIf(this.state.staged, staged),\n            IDs.modified,\n            ...this.insertIf(this.state.modified, modified),\n            IDs.untracked,\n            ...this.insertIf(this.state.untracked, untracked),\n        ]\n        return ids\n    }\n\n    public render() {\n        const error = this.props.hasError && \"Something Went Wrong!\"\n        const inactive = !this.props.activated && \"Version Control Not Available\"\n        const warning = error || inactive\n        const {\n            IDs,\n            logs,\n            showHelp,\n            loading,\n            committing,\n            filesToCommit,\n            loadingSection,\n            status: { modified, staged, untracked },\n        } = this.props\n\n        const commitInProgress = loading && loadingSection === \"commit\"\n\n        return warning ? (\n            <SectionTitle>\n                <Title>{warning}</Title>\n            </SectionTitle>\n        ) : (\n            <>\n                {!showHelp ? <Title>To show help press \"?\"</Title> : <Help />}\n                <VimNavigator\n                    ids={this.getIds()}\n                    active={this.props.hasFocus && !committing}\n                    onSelected={this.toggleOrAction}\n                    onSelectionChanged={this.props.updateSelection}\n                    render={selectedId => (\n                        <StatusContainer>\n                            <CommitsSection\n                                titleId={IDs.commits}\n                                selectedId={selectedId}\n                                visibility={this.state.commits}\n                                onClick={this.props.handleSelection}\n                                commits={logs.all}\n                                toggleVisibility={() => this.toggleVisibility(IDs.commits)}\n                            />\n                            <StagedSection\n                                titleId={IDs.staged}\n                                icon=\"diff-added\"\n                                files={staged}\n                                selectedId={selectedId}\n                                filesToCommit={filesToCommit}\n                                selectedToCommit={this.isSelected}\n                                visible={this.state.staged}\n                                loading={commitInProgress}\n                                handleSelection={this.props.handleSelection}\n                                toggleVisibility={() => this.toggleVisibility(IDs.staged)}\n                                handleCommitOne={this.handleCommitOne}\n                                handleCommitAll={this.handleCommitAll}\n                                handleCommitMessage={this.handleCommitMessage}\n                                handleCommitCancel={this.handleCommitCancel}\n                            />\n                            <VersionControlStatus\n                                icon=\"diff-modified\"\n                                files={modified}\n                                titleId={IDs.modified}\n                                selectedId={selectedId}\n                                visibility={this.state.modified}\n                                onClick={this.props.handleSelection}\n                                toggleVisibility={() => this.toggleVisibility(IDs.modified)}\n                            />\n                            <VersionControlStatus\n                                files={untracked}\n                                icon=\"diff-ignored\"\n                                titleId={IDs.untracked}\n                                selectedId={selectedId}\n                                visibility={this.state.untracked}\n                                onClick={this.props.handleSelection}\n                                toggleVisibility={() => this.toggleVisibility(IDs.untracked)}\n                            />\n                        </StatusContainer>\n                    )}\n                />\n            </>\n        )\n    }\n}\n\nconst mapStateToProps = (state: VersionControlState): IStateProps => ({\n    status: state.status,\n    hasFocus: state.hasFocus,\n    hasError: state.hasError,\n    activated: state.activated,\n    committing: state.commit.active,\n    message: state.commit.message,\n    selectedItem: state.selected,\n    commits: state.commit.previousCommits,\n    filesToCommit: state.commit.files,\n    showHelp: state.help.active,\n    loading: state.loading.active,\n    loadingSection: state.loading.type,\n    logs: state.logs,\n})\n\nconst ConnectedGitComponent = connect<IStateProps, IDispatchProps, IProps>(\n    mapStateToProps,\n    VersionControlActions,\n)(VersionControlView)\n\nexport default ConnectedGitComponent\n"
  },
  {
    "path": "browser/src/Services/VersionControl/index.ts",
    "content": "export {\n    Diff,\n    Summary,\n    SupportedProviders,\n    default as VersionControlProvider,\n} from \"./VersionControlProvider\"\nexport { activate, getInstance, VersionControlManager } from \"./VersionControlManager\"\nexport { default as VersionControlPane } from \"./VersionControlPane\"\nexport { default as store } from \"./VersionControlStore\"\nexport { default as VersionControlView } from \"./VersionControlView\"\n"
  },
  {
    "path": "browser/src/Services/VimConfigurationSynchronizer.ts",
    "content": "/**\n * VimConfigurationSynchronizer\n *\n * Helper method to synchronize configuration settings of the form:\n * `vim.globals.xxxx`\n *  Ex: vim.globals.python_host_prog\n * `vim.setting.xxxx`\n */\n\nimport { INeovimInstance } from \"./../neovim/NeovimInstance\"\n\nexport interface IConfigurationValues {\n    [key: string]: any\n}\n\nconst vimGlobalPrefix = \"vim.global.\"\nconst vimSettingPrefix = \"vim.setting.\"\n\n// TODO:\n// - `onConfigChanged` with updated values\n// - Handle initial load case\n// - Update documentation / default config\nexport const synchronizeConfiguration = (\n    neovimInstance: INeovimInstance,\n    configuration: IConfigurationValues,\n) => {\n    const vimSettingKeys: string[] = Object.keys(configuration).filter(\n        key => key.indexOf(vimSettingPrefix) === 0,\n    )\n\n    vimSettingKeys.forEach(key => {\n        const vimSettingValue: any = configuration[key]\n\n        const baseSettingName = key.substring(vimSettingPrefix.length, key.length)\n\n        if (typeof vimSettingValue === \"boolean\") {\n            const settingValue = vimSettingValue ? baseSettingName : \"no\" + baseSettingName\n            neovimInstance.command(`set ${settingValue}`)\n        } else {\n            neovimInstance.command(`set ${baseSettingName}=${vimSettingValue}`)\n        }\n    })\n\n    const vimGlobalKeys: string[] = Object.keys(configuration).filter(\n        key => key.indexOf(vimGlobalPrefix) === 0,\n    )\n\n    vimGlobalKeys.forEach(key => {\n        const vimGlobalValue: any = configuration[key]\n\n        const globalSettingName = key.substring(vimGlobalPrefix.length, key.length)\n        neovimInstance.command(`let g:${globalSettingName}=${vimGlobalValue}`)\n    })\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/LinearSplitProvider.ts",
    "content": "/**\n * TreeSplitProvider.ts\n *\n * Composite split provider responsible for managing\n * a tree-based hierarchy of horizontal and vertical splits\n */\n\nimport {\n    Direction,\n    IAugmentedSplitInfo,\n    ISplitInfo,\n    IWindowSplitProvider,\n    SingleSplitProvider,\n    SplitDirection,\n} from \"./index\"\n\nexport const getInverseDirection = (splitDirection: SplitDirection): SplitDirection => {\n    switch (splitDirection) {\n        case \"horizontal\":\n            return \"vertical\"\n        case \"vertical\":\n        default:\n            return \"horizontal\"\n    }\n}\n\nexport class LinearSplitProvider implements IWindowSplitProvider {\n    constructor(\n        private _direction: SplitDirection,\n        private _splitProviders: IWindowSplitProvider[] = [],\n    ) {}\n\n    public contains(split: IAugmentedSplitInfo): boolean {\n        return this._getProviderForSplit(split) != null\n    }\n\n    public close(split: IAugmentedSplitInfo): boolean {\n        const containingSplit = this._getProviderForSplit(split)\n\n        if (!containingSplit) {\n            return false\n        }\n\n        const handled = containingSplit.close(split)\n\n        if (handled) {\n            return true\n        }\n\n        // If it was unhandled by the split provider, but the provider contains it, then we'll remove the provider\n        this._splitProviders = this._splitProviders.filter(prov => prov !== containingSplit)\n        return true\n    }\n\n    public split(\n        split: IAugmentedSplitInfo,\n        direction: SplitDirection,\n        referenceSplit?: IAugmentedSplitInfo,\n    ): boolean {\n        // If there are no children, we can just match direction\n        if (this._splitProviders.length === 0) {\n            this._direction = getInverseDirection(direction)\n            this._splitProviders.push(new SingleSplitProvider(split))\n            return true\n        }\n\n        // If there is no reference split, we can just tack this split on\n        if (!referenceSplit) {\n            this._splitProviders.push(new SingleSplitProvider(split))\n            return true\n        }\n\n        const containingSplit = this._getProviderForSplit(referenceSplit)\n\n        if (!containingSplit) {\n            return false\n        }\n\n        const result = containingSplit.split(split, direction, referenceSplit)\n\n        // Containing split handled it, so we're good\n        if (result) {\n            return true\n        }\n\n        // If the split requested is oriented differently,\n        // create a new provider to handle that\n        if (direction !== this._direction) {\n            const singleSplitProvider = new SingleSplitProvider(split)\n            this._splitProviders.push(singleSplitProvider)\n        } else {\n            // Otherwise, we can - let's wrap up the split in a provider\n\n            const previousIndex = this._splitProviders.indexOf(containingSplit)\n            const elementsBefore = this._splitProviders.slice(0, previousIndex)\n            const elementsAfter = this._splitProviders.slice(\n                previousIndex + 1,\n                this._splitProviders.length,\n            )\n\n            const children = [containingSplit, new SingleSplitProvider(split)]\n            const childSplitProvider = new LinearSplitProvider(\n                getInverseDirection(this._direction),\n                children,\n            )\n\n            this._splitProviders = [...elementsBefore, childSplitProvider, ...elementsAfter]\n        }\n\n        return true\n    }\n\n    public move(split: IAugmentedSplitInfo, direction: Direction): IAugmentedSplitInfo {\n        if (!split) {\n            if (this._direction === \"horizontal\") {\n                const index = direction === \"left\" ? this._splitProviders.length - 1 : 0\n                return this._splitProviders[index].move(split, direction)\n            } else {\n                const index = direction === \"up\" ? this._splitProviders.length - 1 : 0\n                return this._splitProviders[index].move(split, direction)\n            }\n        }\n\n        const containingSplit = this._getProviderForSplit(split)\n\n        if (!containingSplit) {\n            return null\n        }\n\n        const result = containingSplit.move(split, direction)\n\n        if (result) {\n            return result\n        }\n\n        if (!this._canHandleMove(direction)) {\n            return null\n        }\n\n        // Since this wasn't handled by the containing split, let's try and handle it\n        const originalIndex = this._splitProviders.indexOf(containingSplit)\n\n        let increment = -1\n\n        if (\n            (this._direction === \"horizontal\" && direction === \"right\") ||\n            (this._direction === \"vertical\" && direction === \"down\")\n        ) {\n            increment = 1\n        }\n\n        const newIndex = originalIndex + increment\n\n        if (newIndex < 0 || newIndex >= this._splitProviders.length) {\n            return null\n        }\n\n        // Move into the next split over\n        return this._splitProviders[newIndex].move(null, direction)\n    }\n\n    public getState(): ISplitInfo<IAugmentedSplitInfo> {\n        if (this._splitProviders.length === 0) {\n            return null\n        }\n\n        return {\n            type: \"Split\",\n            direction: this._direction,\n            splits: this._splitProviders.map(sp => sp.getState()).filter(s => s !== null),\n        }\n    }\n\n    private _canHandleMove(direction: Direction): boolean {\n        switch (direction) {\n            case \"up\":\n                return this._direction === \"vertical\"\n            case \"down\":\n                return this._direction === \"vertical\"\n            case \"left\":\n                return this._direction === \"horizontal\"\n            case \"right\":\n                return this._direction === \"horizontal\"\n            default:\n                return false\n        }\n    }\n\n    private _getProviderForSplit(split: IAugmentedSplitInfo): IWindowSplitProvider {\n        const providers = this._splitProviders.filter(prov => prov.contains(split))\n\n        return providers.length > 0 ? providers[0] : null\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/RelationalSplitNavigator.ts",
    "content": "/**\n * RelationalSplitProvider.ts\n *\n * Composite split provider responsible for managing\n * navigation relationships between other split provdiers\n */\n\nimport { Direction, getInverseDirection, IAugmentedSplitInfo, IWindowSplitNavigator } from \"./index\"\n\nexport interface WindowSplitRelationship {\n    from: IWindowSplitNavigator\n    to: IWindowSplitNavigator\n    direction: string\n}\n\nexport class RelationalSplitNavigator implements IWindowSplitNavigator {\n    private _relationships: WindowSplitRelationship[] = []\n    private _providers: IWindowSplitNavigator[] = []\n\n    public setRelationship(\n        from: IWindowSplitNavigator,\n        to: IWindowSplitNavigator,\n        direction: Direction,\n    ): void {\n        this._relationships.push({\n            from,\n            to,\n            direction,\n        })\n\n        // Also push the inverse\n        this._relationships.push({\n            from: to,\n            to: from,\n            direction: getInverseDirection(direction),\n        })\n\n        this._addToProvidersIfNeeded(from)\n        this._addToProvidersIfNeeded(to)\n    }\n\n    public contains(split: IAugmentedSplitInfo): boolean {\n        return this._getContainingSplit(split) !== null\n    }\n\n    public move(split: IAugmentedSplitInfo, direction: Direction): IAugmentedSplitInfo {\n        // If there is no current split, that means we are entering\n        if (split === null) {\n            // Need to find the furthest split in the *reverse* direction.\n            // For example, if we are moving *right* into this split,\n            // we want to grab the furthest *left* split\n            const reverseDirection = getInverseDirection(direction)\n            const splitProvider = this._getFurthestSplitInDirection(reverseDirection, null)\n            return splitProvider.move(null, direction)\n        }\n\n        const containingSplit = this._getContainingSplit(split)\n\n        if (!containingSplit) {\n            return null\n        }\n\n        // Check if the containing split handled it\n        const moveResult = containingSplit.move(split, direction)\n        if (moveResult) {\n            return moveResult\n        }\n\n        // The containing split couldn't handle it, so let's see if there is a relationship from the containing split\n        const applicableRelationship = this._relationships.filter(\n            rel => rel.from === containingSplit && rel.direction === direction,\n        )\n\n        if (applicableRelationship.length > 0) {\n            return applicableRelationship[0].to.move(null, direction)\n        } else {\n            return null\n        }\n    }\n\n    private _getFurthestSplitInDirection(\n        direction: Direction,\n        split: IWindowSplitNavigator,\n    ): IWindowSplitNavigator {\n        const splits = this._relationships.filter(\n            rel => (rel.direction === direction && rel.from === split) || split === null,\n        )\n\n        // Base case - there are no further splits in that direction, so return the current one\n        if (splits.length === 0) {\n            return split\n        }\n\n        // Recursive case - take the 'to' split and see if there is anything further\n        const currentRelationship = splits[0]\n        return this._getFurthestSplitInDirection(direction, currentRelationship.to)\n    }\n\n    private _getContainingSplit(split: IAugmentedSplitInfo): IWindowSplitNavigator {\n        const providers = this._providers.filter(s => s.contains(split))\n        return providers.length === 0 ? null : providers[0]\n    }\n\n    private _addToProvidersIfNeeded(provider: IWindowSplitNavigator): void {\n        if (this._providers.indexOf(provider) === -1) {\n            this._providers.push(provider)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/SingleSplitProvider.ts",
    "content": "/**\n * SingleSplitProvider.ts\n *\n * Split provider for a leaf node\n */\n\nimport {\n    Direction,\n    IAugmentedSplitInfo,\n    IWindowSplitProvider,\n    SplitDirection,\n    SplitOrLeaf,\n} from \"./index\"\n\nexport class SingleSplitProvider implements IWindowSplitProvider {\n    constructor(private _split: IAugmentedSplitInfo) {}\n\n    public contains(split: IAugmentedSplitInfo): boolean {\n        return this._split === split\n    }\n\n    public move(split: IAugmentedSplitInfo, direction: Direction): IAugmentedSplitInfo {\n        if (split === null) {\n            return this._split\n        } else {\n            return null\n        }\n    }\n\n    public split(split: IAugmentedSplitInfo, direction: SplitDirection): boolean {\n        return false\n    }\n\n    public close(split: IAugmentedSplitInfo): boolean {\n        return false\n    }\n\n    public getState(): SplitOrLeaf<IAugmentedSplitInfo> {\n        return {\n            type: \"Leaf\",\n            contents: this._split,\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/WindowDock.ts",
    "content": "/**\n * WindowDock.ts\n */\n\nimport { Direction, IAugmentedSplitInfo, IWindowSplitNavigator } from \"./index\"\n\nexport type DockStateGetter = () => IAugmentedSplitInfo[]\n\nexport class WindowDockNavigator implements IWindowSplitNavigator {\n    constructor(private _stateGetter: DockStateGetter) {}\n\n    public contains(split: IAugmentedSplitInfo): boolean {\n        const splits = this._stateGetter()\n        return splits.indexOf(split) >= 0\n    }\n\n    public move(startSplit: IAugmentedSplitInfo, direction: Direction): IAugmentedSplitInfo {\n        const splits = this._stateGetter()\n\n        const currentIndex = splits.indexOf(startSplit)\n\n        if (currentIndex === -1) {\n            if (direction === \"left\") {\n                return splits[splits.length - 1]\n            } else if (direction === \"right\") {\n                return splits[0]\n            } else {\n                return null\n            }\n        }\n\n        // TODO: Generalize this - this is baked for a 'left dock' case right now\n        const newIndex = direction === \"left\" ? currentIndex - 1 : currentIndex + 1\n\n        if (newIndex >= 0 && newIndex < splits.length) {\n            return splits[newIndex]\n        } else {\n            return null\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/WindowManager.ts",
    "content": "/**\n * WindowManager.ts\n *\n * Responsible for managing state of the editor collection, and\n * switching between active editors.\n *\n * It also provides convenience methods for hooking events\n * to the active editor, and managing transitions between editors.\n */\n\nimport { remote } from \"electron\"\n\nimport { Store } from \"redux\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport { Direction, SplitDirection } from \"./index\"\nimport { LinearSplitProvider } from \"./LinearSplitProvider\"\nimport { RelationalSplitNavigator } from \"./RelationalSplitNavigator\"\nimport { WindowDockNavigator } from \"./WindowDock\"\n\nimport {\n    createStore,\n    IAugmentedSplitInfo,\n    ISplitInfo,\n    leftDockSelector,\n    WindowState,\n} from \"./WindowManagerStore\"\n\nexport class WindowSplitHandle implements Oni.WindowSplitHandle {\n    public get id(): string {\n        return this._id\n    }\n\n    public get isVisible(): boolean {\n        return this._store.getState().hiddenSplits.indexOf(this._id) === -1\n    }\n\n    public get isFocused(): boolean {\n        return this._store.getState().focusedSplitId === this._id\n    }\n\n    constructor(\n        private _store: Store<WindowState>,\n        private _windowManager: WindowManager,\n        private _id: string,\n    ) {}\n\n    public hide(): void {\n        this._store.dispatch({\n            type: \"HIDE_SPLIT\",\n            splitId: this._id,\n        })\n\n        this._windowManager.swapToPreviousSplit(this._id)\n    }\n\n    public show(): void {\n        this._store.dispatch({\n            type: \"SHOW_SPLIT\",\n            splitId: this._id,\n        })\n    }\n\n    public focus(): void {\n        // TODO:\n        this._windowManager.focusSplit(this._id)\n    }\n\n    public setSize(size: number): void {\n        // TODO\n    }\n\n    public close(): void {\n        this._windowManager.close(this._id)\n    }\n}\n\nexport class AugmentedWindow implements IAugmentedSplitInfo {\n    public get id(): string {\n        return this._id\n    }\n\n    constructor(private _id: string, private _innerSplit: Oni.IWindowSplit | any) {}\n\n    public get innerSplit(): Oni.IWindowSplit {\n        return this._innerSplit\n    }\n\n    public render(): JSX.Element {\n        return this._innerSplit.render()\n    }\n\n    public enter(): void {\n        if (this._innerSplit.enter) {\n            this._innerSplit.enter()\n        }\n    }\n\n    public leave(): void {\n        if (this._innerSplit.leave) {\n            this._innerSplit.leave()\n        }\n    }\n}\n\nexport class WindowManager {\n    private _lastId: number = 0\n    private _idToSplit: { [key: string]: IAugmentedSplitInfo } = {}\n\n    private _onUnhandledMoveEvent = new Event<Direction>()\n\n    private _leftDock: WindowDockNavigator = null\n    private _primarySplit: LinearSplitProvider\n    private _rootNavigator: RelationalSplitNavigator\n\n    // Queue of recently focused windows, to fall-back to\n    // when closing a window.\n    private _focusQueue: string[] = []\n\n    private _store: Store<WindowState>\n\n    public get onUnhandledMove(): IEvent<Direction> {\n        return this._onUnhandledMoveEvent\n    }\n\n    private _onFocusChanged = new Event<ISplitInfo<Oni.IWindowSplit>>()\n\n    public get onFocusChanged(): IEvent<ISplitInfo<Oni.IWindowSplit>> {\n        return this._onFocusChanged\n    }\n\n    public get splitRoot(): ISplitInfo<Oni.IWindowSplit> {\n        return this._primarySplit.getState() as ISplitInfo<Oni.IWindowSplit>\n    }\n\n    public get store(): Store<WindowState> {\n        return this._store\n    }\n\n    get activeSplitHandle(): WindowSplitHandle {\n        return new WindowSplitHandle(this._store, this, this.activeSplit.id)\n    }\n\n    private get activeSplit(): IAugmentedSplitInfo {\n        const focusedSplit = this._store.getState().focusedSplitId\n\n        if (!focusedSplit) {\n            return null\n        }\n\n        return this._idToSplit[focusedSplit]\n    }\n\n    constructor() {\n        this._rootNavigator = new RelationalSplitNavigator()\n\n        const browserWindow = remote.getCurrentWindow()\n\n        browserWindow.on(\"blur\", () => {\n            if (this.activeSplit) {\n                this.activeSplit.leave()\n            }\n        })\n\n        browserWindow.on(\"focus\", () => {\n            if (this.activeSplit) {\n                this.activeSplit.enter()\n            }\n        })\n\n        this._store = createStore()\n        this._leftDock = new WindowDockNavigator(() => leftDockSelector(this._store.getState()))\n        this._primarySplit = new LinearSplitProvider(\"horizontal\")\n        this._rootNavigator.setRelationship(this._leftDock, this._primarySplit, \"right\")\n    }\n\n    public createSplit(\n        splitLocation: Direction | SplitDirection,\n        newSplit: Oni.IWindowSplit,\n        referenceSplit?: Oni.IWindowSplit,\n    ): WindowSplitHandle {\n        const nextId = this._lastId++\n        const windowId = \"oni.window.\" + nextId.toString()\n\n        const augmentedWindow = new AugmentedWindow(windowId, newSplit)\n\n        this._idToSplit[windowId] = augmentedWindow\n\n        switch (splitLocation) {\n            case \"right\":\n            case \"up\":\n            case \"down\":\n            case \"left\": {\n                this._store.dispatch({\n                    type: \"ADD_DOCK_SPLIT\",\n                    dock: splitLocation,\n                    split: augmentedWindow,\n                })\n                break\n            }\n            case \"horizontal\":\n            case \"vertical\":\n                const augmentedRefSplit =\n                    this._getAugmentedWindowSplitFromSplit(referenceSplit) || this.activeSplit\n                this._primarySplit.split(augmentedWindow, splitLocation, augmentedRefSplit)\n                const newState = this._primarySplit.getState() as ISplitInfo<Oni.IWindowSplit>\n\n                this._store.dispatch({\n                    type: \"SET_PRIMARY_SPLITS\",\n                    splits: newState,\n                })\n\n                this._focusNewSplit(augmentedWindow)\n        }\n\n        return new WindowSplitHandle(this._store, this, windowId)\n    }\n\n    public getSplitHandle(split: Oni.IWindowSplit): WindowSplitHandle {\n        const augmentedSplit = this._getAugmentedWindowSplitFromSplit(split)\n        return new WindowSplitHandle(this._store, this, augmentedSplit.id)\n    }\n\n    public move(direction: Direction): void {\n        const focusedSplit = this._store.getState().focusedSplitId\n\n        if (!focusedSplit) {\n            return\n        }\n\n        const activeSplit = this._idToSplit[focusedSplit]\n\n        if (!activeSplit) {\n            return\n        }\n\n        const newSplit = this._rootNavigator.move(activeSplit, direction)\n\n        if (newSplit) {\n            this._focusNewSplit(newSplit)\n        } else {\n            this._onUnhandledMoveEvent.dispatch(direction)\n        }\n    }\n\n    public moveLeft(): void {\n        this.move(\"left\")\n    }\n\n    public moveRight(): void {\n        this.move(\"right\")\n    }\n\n    public moveUp(): void {\n        this.move(\"up\")\n    }\n\n    public moveDown(): void {\n        this.move(\"down\")\n    }\n\n    public close(splitId: string) {\n        this.swapToPreviousSplit(splitId)\n        delete this._idToSplit[splitId]\n    }\n\n    // Swaps focus to the most recently focused window, and hides\n    // the passed split.\n    public swapToPreviousSplit(splitId: string) {\n        const currentActiveSplit = this.activeSplit\n\n        // Send focus back to most recently focused window\n        if (currentActiveSplit.id === splitId) {\n            const candidateSplits = this._focusQueue.filter(\n                f => f !== splitId && this._idToSplit[f],\n            )\n\n            this._focusQueue = candidateSplits\n\n            if (this._focusQueue.length > 0) {\n                const splitToFocus = this._focusQueue[0]\n                this._focusNewSplit(this._idToSplit[splitToFocus])\n            }\n        }\n\n        const split = this._idToSplit[splitId]\n        this._primarySplit.close(split)\n\n        const state = this._primarySplit.getState()\n        this._store.dispatch({\n            type: \"SET_PRIMARY_SPLITS\",\n            splits: state,\n        })\n    }\n\n    public focusSplit(splitId: string): void {\n        const split = this._idToSplit[splitId]\n        this._focusNewSplit(split)\n    }\n\n    private _getAugmentedWindowSplitFromSplit(split: Oni.IWindowSplit): IAugmentedSplitInfo {\n        const augmentedWindows = Object.values(this._idToSplit)\n        return augmentedWindows.find(aw => aw.innerSplit === split) || null\n    }\n\n    private _focusNewSplit(newSplit: any): void {\n        if (this.activeSplit && this.activeSplit.leave) {\n            this.activeSplit.leave()\n        }\n\n        this._store.dispatch({\n            type: \"SET_FOCUSED_SPLIT\",\n            splitId: newSplit.id,\n        })\n\n        const filteredSplits = this._focusQueue.filter(f => f !== newSplit.id)\n        this._focusQueue = [newSplit.id, ...filteredSplits]\n\n        if (newSplit && newSplit.enter) {\n            newSplit.enter()\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/WindowManagerStore.ts",
    "content": "/**\n * WindowManagerStore.ts\n *\n * Redux store for managing window state\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { Reducer, Store } from \"redux\"\nimport { createStore as createReduxStore } from \"./../../Redux\"\n\nimport { Direction, ISplitInfo, SplitDirection } from \"./index\"\n\nexport interface IAugmentedSplitInfo extends Oni.IWindowSplit {\n    // Internal bookkeeping\n    id: string\n\n    innerSplit: Oni.IWindowSplit\n\n    // Potential API methods\n    enter?(): void\n    leave?(): void\n}\n\nexport type SplitOrLeaf<T> = ISplitInfo<T> | ISplitLeaf<T>\n\nexport interface ISplitInfo<T> {\n    type: \"Split\"\n    splits: Array<SplitOrLeaf<T>>\n    direction: SplitDirection\n}\n\nexport interface ISplitLeaf<T> {\n    type: \"Leaf\"\n    contents: T\n}\n\ntype WindowActions =\n    | {\n          type: \"ADD_DOCK_SPLIT\"\n          dock: Direction\n          split: IAugmentedSplitInfo\n      }\n    | {\n          type: \"SET_PRIMARY_SPLITS\"\n          splits: ISplitInfo<IAugmentedSplitInfo>\n      }\n    | {\n          type: \"SET_FOCUSED_SPLIT\"\n          splitId: string\n      }\n    | {\n          type: \"SHOW_SPLIT\"\n          splitId: string\n      }\n    | {\n          type: \"HIDE_SPLIT\"\n          splitId: string\n      }\n\nexport interface DockWindows {\n    [key: string]: IAugmentedSplitInfo[]\n}\n\nexport const DefaultDocksState: DockWindows = {\n    left: [],\n    right: [],\n    up: [],\n    down: [],\n}\n\nexport interface WindowState {\n    docks: DockWindows\n\n    primarySplit: ISplitInfo<IAugmentedSplitInfo>\n\n    focusedSplitId: string\n    hiddenSplits: string[]\n}\n\nexport const DefaultWindowState: WindowState = {\n    docks: DefaultDocksState,\n    primarySplit: null,\n    focusedSplitId: null,\n    hiddenSplits: [],\n}\n\nexport const reducer: Reducer<WindowState> = (\n    state: WindowState = DefaultWindowState,\n    action: WindowActions,\n) => {\n    switch (action.type) {\n        case \"SET_PRIMARY_SPLITS\":\n            return {\n                ...state,\n                primarySplit: action.splits,\n            }\n        case \"SET_FOCUSED_SPLIT\":\n            return {\n                ...state,\n                focusedSplitId: action.splitId,\n            }\n        case \"SHOW_SPLIT\":\n            return {\n                ...state,\n                hiddenSplits: state.hiddenSplits.filter(s => s !== action.splitId),\n            }\n        case \"HIDE_SPLIT\":\n            return {\n                ...state,\n                hiddenSplits: [\n                    ...state.hiddenSplits.filter(s => s !== action.splitId),\n                    action.splitId,\n                ],\n            }\n        default:\n            return {\n                ...state,\n                docks: docksReducer(state.docks, action),\n            }\n    }\n}\n\nexport const docksReducer: Reducer<DockWindows> = (\n    state: DockWindows = DefaultDocksState,\n    action: WindowActions,\n) => {\n    switch (action.type) {\n        case \"ADD_DOCK_SPLIT\":\n            return {\n                ...state,\n                [action.dock]: [...state[action.dock], action.split],\n            }\n        default:\n            return state\n    }\n}\n\nexport const leftDockSelector = (state: WindowState) => {\n    return state.docks.left.filter(s => state.hiddenSplits.indexOf(s.id) === -1)\n}\n\nexport const createStore = (): Store<WindowState> => {\n    return createReduxStore(\"WindowManager\", reducer, DefaultWindowState, [])\n}\n"
  },
  {
    "path": "browser/src/Services/WindowManager/index.ts",
    "content": "/**\n * WindowManager.ts\n *\n * Responsible for managing state of the editor collection, and\n * switching between active editors.\n *\n * It also provides convenience methods for hooking events\n * to the active editor, and managing transitions between editors.\n */\n\nexport * from \"./layoutFromSplitInfo\"\nexport * from \"./LinearSplitProvider\"\nexport * from \"./RelationalSplitNavigator\"\nexport * from \"./SingleSplitProvider\"\nexport * from \"./WindowDock\"\nexport * from \"./WindowManager\"\nexport * from \"./WindowManagerStore\"\n\n// TODO: Possible API types?\nexport type Direction = \"up\" | \"down\" | \"left\" | \"right\"\nexport type SplitDirection = \"horizontal\" | \"vertical\"\n\nexport const getInverseDirection = (direction: Direction): Direction => {\n    switch (direction) {\n        case \"up\":\n            return \"down\"\n        case \"down\":\n            return \"up\"\n        case \"left\":\n            return \"right\"\n        case \"right\":\n            return \"left\"\n        default:\n            return null\n    }\n}\n\nimport { WindowManager } from \"./WindowManager\"\nimport { IAugmentedSplitInfo, SplitOrLeaf } from \"./WindowManagerStore\"\n\n/**\n * Interface for something that can navigate between window splits\n */\nexport interface IWindowSplitNavigator {\n    contains(split: IAugmentedSplitInfo): boolean\n    move(startSplit: IAugmentedSplitInfo, direction: Direction): IAugmentedSplitInfo\n}\n\n/**\n * Interface for something that can manage window splits:\n * - Navigating splits\n * - Creating a new split\n * - Removing a split\n * Later - resizing a split?\n */\nexport interface IWindowSplitProvider extends IWindowSplitNavigator {\n    split(\n        newSplit: IAugmentedSplitInfo,\n        direction: SplitDirection,\n        referenceSplit?: IAugmentedSplitInfo,\n    ): boolean\n    close(split: IAugmentedSplitInfo): boolean\n    getState(): SplitOrLeaf<IAugmentedSplitInfo>\n}\n\nexport const windowManager = new WindowManager()\n"
  },
  {
    "path": "browser/src/Services/WindowManager/layoutFromSplitInfo.ts",
    "content": "/**\n * layoutFromSplitInfo.ts\n *\n * Function to layout splits into a particular window\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { IAugmentedSplitInfo, ISplitInfo, SplitOrLeaf } from \"./WindowManagerStore\"\n\nexport interface LayoutResultInfo {\n    rectangle: Oni.Shapes.Rectangle\n    split: IAugmentedSplitInfo\n}\n\nexport interface LayoutResult {\n    [windowId: string]: LayoutResultInfo\n}\n\nexport const layoutFromSplitInfo = (\n    splits: ISplitInfo<IAugmentedSplitInfo>,\n    width: number,\n    height: number,\n): LayoutResult => {\n    return layoutFromSplitInfoHelper(splits, Oni.Shapes.Rectangle.create(0, 0, width, height))\n}\n\nconst layoutFromSplitInfoHelper = (\n    split: SplitOrLeaf<IAugmentedSplitInfo>,\n    rectangle: Oni.Shapes.Rectangle,\n): LayoutResult => {\n    // Base case..\n    if (split.type === \"Leaf\") {\n        return {\n            [split.contents.id]: {\n                rectangle,\n                split: split.contents,\n            },\n        }\n    }\n\n    if (split.splits.length === 0) {\n        return {}\n    }\n\n    // Recursive case\n    //\n    // TODO: Handle specified sizes for the windows. We're just distributing the space evenly, currently.\n    const splitWidth =\n        split.direction === \"horizontal\" ? rectangle.width / split.splits.length : rectangle.width\n    const splitHeight =\n        split.direction === \"vertical\" ? rectangle.height / split.splits.length : rectangle.height\n\n    let ret = {}\n\n    for (let i = 0; i < split.splits.length; i++) {\n        const x = split.direction === \"horizontal\" ? rectangle.x + splitWidth * i : rectangle.x\n        const y = split.direction === \"vertical\" ? rectangle.y + splitHeight * i : rectangle.y\n\n        const rect = Oni.Shapes.Rectangle.create(x, y, splitWidth, splitHeight)\n\n        ret = {\n            ...ret,\n            ...layoutFromSplitInfoHelper(split.splits[i], rect),\n        }\n    }\n\n    return ret\n}\n"
  },
  {
    "path": "browser/src/Services/Workspace/Workspace.ts",
    "content": "/**\n * Workspace.ts\n *\n * The 'workspace' is responsible for managing the state of the current project:\n *  - The current / active directory (and 'Open Folder')\n */\n\nimport { remote } from \"electron\"\nimport * as findup from \"find-up\"\nimport { stat } from \"fs\"\nimport * as path from \"path\"\nimport { promisify } from \"util\"\n\nimport \"rxjs/add/observable/defer\"\nimport \"rxjs/add/observable/from\"\nimport \"rxjs/add/operator/concatMap\"\nimport \"rxjs/add/operator/toPromise\"\nimport { Observable } from \"rxjs/Observable\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as Helpers from \"./../../Plugins/Api/LanguageClient/LanguageClientHelpers\"\n\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport { convertTextDocumentChangesToFileMap } from \"./../Language/Edits\"\n\nimport { WorkspaceConfiguration } from \"./WorkspaceConfiguration\"\n\nconst fsStat = promisify(stat)\n\nexport class Workspace implements Oni.Workspace.Api {\n    private _onDirectoryChangedEvent = new Event<string>()\n    private _onFocusGainedEvent = new Event<Oni.Buffer>()\n    private _onFocusLostEvent = new Event<Oni.Buffer>()\n    private _mainWindow = remote.getCurrentWindow()\n    private _lastActiveBuffer: Oni.Buffer\n    private _activeWorkspace: string\n\n    public get activeWorkspace(): string {\n        return this._activeWorkspace\n    }\n\n    constructor(private _editorManager: EditorManager, private _configuration: Configuration) {\n        this._mainWindow.on(\"focus\", () => {\n            this._onFocusGainedEvent.dispatch(this._lastActiveBuffer)\n        })\n\n        this._mainWindow.on(\"blur\", () => {\n            this._lastActiveBuffer = this._editorManager.activeEditor.activeBuffer\n            this._onFocusLostEvent.dispatch(this._lastActiveBuffer)\n        })\n    }\n\n    public get onDirectoryChanged(): IEvent<string> {\n        return this._onDirectoryChangedEvent\n    }\n\n    public async changeDirectory(newDirectory: string) {\n        const exists = await this.pathIsDir(newDirectory)\n        const dir = exists ? newDirectory : null\n        if (newDirectory && exists) {\n            process.chdir(newDirectory)\n        }\n\n        this._activeWorkspace = dir\n        this._onDirectoryChangedEvent.dispatch(dir)\n    }\n\n    public async applyEdits(edits: types.WorkspaceEdit): Promise<void> {\n        const editsToUse = edits.documentChanges\n            ? convertTextDocumentChangesToFileMap(edits.documentChanges)\n            : edits.changes\n\n        const files = Object.keys(editsToUse)\n\n        // TODO: Show modal to grab input\n        // await editorManager.activeEditor.openFiles(files)\n\n        const deferredEdits = await files.map((fileUri: string) => {\n            return Observable.defer(async () => {\n                const changes = editsToUse[fileUri]\n                const fileName = Helpers.unwrapFileUriPath(fileUri)\n                // TODO: Sort changes?\n                Log.verbose(\"[Workspace] Opening file: \" + fileName)\n                const buf = await this._editorManager.activeEditor.openFile(fileName)\n                Log.verbose(\n                    \"[Workspace] Got buffer for file: \" + buf.filePath + \" and id: \" + buf.id,\n                )\n                await buf.applyTextEdits(changes)\n                Log.verbose(\"[Workspace] Applied \" + changes.length + \" edits to buffer\")\n            })\n        })\n\n        await Observable.from(deferredEdits)\n            .concatMap(de => de)\n            .toPromise()\n\n        Log.verbose(\"[Workspace] Completed applying edits\")\n\n        // Hide modal\n    }\n\n    public get onFocusGained(): IEvent<Oni.Buffer> {\n        return this._onFocusGainedEvent\n    }\n\n    public get onFocusLost(): IEvent<Oni.Buffer> {\n        return this._onFocusLostEvent\n    }\n\n    public pathIsDir = async (p: string) => {\n        try {\n            const stats = await fsStat(p)\n            return stats.isDirectory()\n        } catch (error) {\n            Log.info(error)\n            return false\n        }\n    }\n\n    public navigateToProjectRoot = async (bufferPath: string) => {\n        const projectMarkers = this._configuration.getValue(\"workspace.autoDetectRootFiles\")\n\n        // If the supplied path is a folder, we should use that instead of\n        // moving up a folder again.\n        // Helps when calling Oni from the CLI with \"oni .\"\n        const cwd = (await this.pathIsDir(bufferPath)) ? bufferPath : path.dirname(bufferPath)\n\n        const filePath = await findup(projectMarkers, { cwd })\n        if (filePath) {\n            const projectRoot = path.dirname(filePath)\n            return projectRoot !== this._activeWorkspace ? this.changeDirectory(projectRoot) : null\n        }\n    }\n\n    public openFolder(): void {\n        const dialogOptions: any = {\n            title: \"Open Folder\",\n            properties: [\"openDirectory\"],\n        }\n\n        remote.dialog.showOpenDialog(\n            remote.getCurrentWindow(),\n            dialogOptions,\n            async (folder: string[]) => {\n                if (!folder || !folder[0]) {\n                    return\n                }\n\n                const folderToOpen = folder[0]\n                await this.changeDirectory(folderToOpen)\n            },\n        )\n    }\n\n    public autoDetectWorkspace(filePath: string): void {\n        const settings = this._configuration.getValue(\"workspace.autoDetectWorkspace\")\n        switch (settings) {\n            case \"never\":\n                break\n            case \"always\":\n                this.navigateToProjectRoot(filePath)\n                break\n            case \"noworkspace\":\n            default:\n                if (!this._activeWorkspace) {\n                    this.navigateToProjectRoot(filePath)\n                }\n        }\n    }\n}\n\nlet _workspace: Workspace = null\nlet _workspaceConfiguration: WorkspaceConfiguration = null\n\nexport const activate = (\n    configuration: Configuration,\n    editorManager: EditorManager,\n    workspaceToLoad?: string,\n): void => {\n    _workspace = new Workspace(editorManager, configuration)\n\n    _workspaceConfiguration = new WorkspaceConfiguration(configuration, _workspace)\n\n    const defaultWorkspace = workspaceToLoad || configuration.getValue(\"workspace.defaultWorkspace\")\n\n    if (defaultWorkspace) {\n        _workspace.changeDirectory(defaultWorkspace)\n    }\n\n    _workspace.onDirectoryChanged.subscribe(newDirectory => {\n        configuration.setValues({ \"workspace.defaultWorkspace\": newDirectory }, true)\n    })\n}\n\nexport const getInstance = (): Workspace => {\n    return _workspace\n}\n\nexport const getConfigurationInstance = (): WorkspaceConfiguration => {\n    return _workspaceConfiguration\n}\n"
  },
  {
    "path": "browser/src/Services/Workspace/WorkspaceCommands.ts",
    "content": "/**\n * WorkspaceCommands.ts\n *\n * Commands registered for the workspace\n */\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\n\nimport { CallbackCommand, commandManager } from \"./../CommandManager\"\nimport { Configuration } from \"./../Configuration\"\nimport { EditorManager } from \"./../EditorManager\"\nimport * as FileMappings from \"./../FileMappings\"\nimport { SnippetManager } from \"./../Snippets\"\n\nimport { Workspace } from \"./Workspace\"\n\nexport const activateCommands = (\n    configuration: Configuration,\n    editorManager: EditorManager,\n    snippetManager: SnippetManager,\n    workspace: Workspace,\n) => {\n    const openTestFileInSplit = async () => {\n        const mappingResult = getTestFileMappedToCurrentFile()\n        const mappedFile = mappingResult.fullPath\n        const templateFile = mappingResult.templateFileFullPath\n\n        if (mappedFile) {\n            let snippetToInsert: string = null\n\n            if (!fs.existsSync(mappedFile)) {\n                // Ensure the folder exists for the mapped file\n                const containingFolder = path.dirname(mappedFile)\n                mkdirp.sync(containingFolder)\n\n                if (templateFile && fs.existsSync(templateFile)) {\n                    snippetToInsert = fs.readFileSync(templateFile).toString(\"utf8\")\n                }\n            }\n\n            await editorManager.activeEditor.openFile(mappedFile)\n\n            if (snippetToInsert) {\n                await snippetManager.insertSnippet(snippetToInsert)\n            }\n        }\n    }\n\n    const hasExistingTestFile = () => {\n        const mappedFile = getTestFileMappedToCurrentFile()\n\n        return mappedFile && fs.existsSync(mappedFile.fullPath)\n    }\n\n    const canCreateTestFile = () => {\n        const mappedFile = getTestFileMappedToCurrentFile()\n\n        return mappedFile && !fs.existsSync(mappedFile.fullPath)\n    }\n\n    const getTestFileMappedToCurrentFile = (): FileMappings.IFileMappingResult => {\n        const mappings: FileMappings.IFileMapping[] = configuration.getValue(\n            \"workspace.testFileMappings\",\n        )\n\n        if (!mappings) {\n            return null\n        }\n\n        // If we have no active workspace, we don't know where test files live.\n        if (!workspace.activeWorkspace) {\n            return null\n        }\n\n        const currentEditor = editorManager.activeEditor\n\n        if (!currentEditor || !currentEditor.activeBuffer) {\n            return null\n        }\n\n        const currentBufferPath = currentEditor.activeBuffer.filePath\n\n        if (!currentBufferPath) {\n            return null\n        }\n\n        const mappedFile = FileMappings.getMappedFile(\n            workspace.activeWorkspace,\n            currentBufferPath,\n            mappings,\n        )\n\n        return mappedFile\n    }\n\n    const commands = [\n        new CallbackCommand(\n            \"workspace.openFolder\",\n            \"Workspace: Open Folder\",\n            \"Set a folder as the working directory for Oni\",\n            () => workspace.openFolder(),\n        ),\n        new CallbackCommand(\n            \"workspace.openTestFile\",\n            \"Workspace: Open Test File\",\n            \"Open the test file corresponding to this source file.\",\n            () => openTestFileInSplit(),\n            () => hasExistingTestFile(),\n        ),\n        new CallbackCommand(\n            \"workspace.createTestFile\",\n            \"Workspace: Create Test File\",\n            \"Create a test file for this source file.\",\n            () => openTestFileInSplit(),\n            () => canCreateTestFile(),\n        ),\n        new CallbackCommand(\n            \"workspace.closeFolder\",\n            \"Workspace: Close Folder\",\n            \"Close the current folder\",\n            async () => workspace.changeDirectory(null),\n            () => !!workspace.activeWorkspace,\n        ),\n    ]\n\n    commands.forEach(c => commandManager.registerCommand(c))\n}\n"
  },
  {
    "path": "browser/src/Services/Workspace/WorkspaceConfiguration.ts",
    "content": "/**\n * WorkspaceConfiguration.ts\n *\n * Responsible for managing settings / loading configuration for current workspace\n */\n\nimport * as fs from \"fs\"\nimport * as Oni from \"oni-api\"\nimport * as path from \"path\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { Configuration } from \"./../Configuration\"\n\nexport const getWorkspaceConfigurationPath = (workspacePath: string): string => {\n    return path.join(workspacePath, \".oni\", \"config.js\")\n}\n\nexport class WorkspaceConfiguration {\n    private _activeWorkspaceConfiguration: string = null\n\n    public get activeWorkspaceConfiguration(): string {\n        return this._activeWorkspaceConfiguration\n    }\n\n    constructor(\n        private _configuration: Configuration,\n        private _workspace: Oni.Workspace.Api,\n        private _fs: typeof fs = fs,\n    ) {\n        this._checkWorkspaceConfiguration()\n\n        this._workspace.onDirectoryChanged.subscribe(() => {\n            this._checkWorkspaceConfiguration()\n        })\n    }\n\n    private _checkWorkspaceConfiguration(): void {\n        const activeWorkspace = this._workspace.activeWorkspace\n\n        if (!activeWorkspace) {\n            return\n        }\n\n        const configurationPath = getWorkspaceConfigurationPath(activeWorkspace)\n\n        if (\n            this._fs.existsSync(configurationPath) &&\n            this._fs.statSync(configurationPath).isFile()\n        ) {\n            Log.info(\"[WorkspaceConfiguration] Found configuration file at: \" + configurationPath)\n            this._loadWorkspaceConfiguration(configurationPath)\n        }\n    }\n\n    private _removePreviousWorkspaceConfiguration(): void {\n        if (this._activeWorkspaceConfiguration) {\n            this._configuration.removeConfigurationFile(this._activeWorkspaceConfiguration)\n            this._activeWorkspaceConfiguration = null\n        }\n    }\n\n    private _loadWorkspaceConfiguration(configurationPath: string): void {\n        Log.info(\n            \"[WorkspaceConfiguration] Loading workspace configuration from: \" + configurationPath,\n        )\n        this._removePreviousWorkspaceConfiguration()\n\n        this._activeWorkspaceConfiguration = configurationPath\n        this._configuration.addConfigurationFile(configurationPath)\n    }\n}\n"
  },
  {
    "path": "browser/src/Services/Workspace/find-up.d.ts",
    "content": "declare module \"find-up\"\n"
  },
  {
    "path": "browser/src/Services/Workspace/index.ts",
    "content": "export * from \"./Workspace\"\nexport * from \"./WorkspaceConfiguration\"\n"
  },
  {
    "path": "browser/src/UI/Icon.tsx",
    "content": "import * as React from \"react\"\n\nexport const Default = \"\"\nexport const Large = \"fa-lg\"\nexport const TwoX = \"fa-2x\"\nexport const ThreeX = \"fa-3x\"\nexport const FourX = \"fa-4x\"\nexport const FiveX = \"fa-5x\"\nexport const NineX = \"fa-9x\"\n\nexport enum IconSize {\n    Default = 0,\n    Large,\n    TwoX,\n    ThreeX,\n    FourX,\n    FiveX,\n    NineX,\n}\n\nexport interface IconProps {\n    name: string\n    size?: IconSize\n    className?: string\n    style?: React.CSSProperties\n}\nconst EmptyStyle: React.CSSProperties = {}\n\nexport class Icon extends React.PureComponent<IconProps, {}> {\n    public render(): JSX.Element {\n        const style = this.props.style || EmptyStyle\n        const className =\n            \"fa fa-\" + this.props.name + \" \" + this._getClassForIconSize(this.props.size as any) // FIXME: undefined\n        const additionalClass = this.props.className || \"\"\n        return <i className={className + additionalClass} style={style} aria-hidden=\"true\" />\n    }\n\n    private _getClassForIconSize(size: IconSize): string {\n        const normalizedSize = size || IconSize.Default\n\n        switch (normalizedSize) {\n            case IconSize.Large:\n                return Large\n            case IconSize.TwoX:\n                return TwoX\n            case IconSize.ThreeX:\n                return ThreeX\n            case IconSize.FourX:\n                return FourX\n            case IconSize.FiveX:\n                return FiveX\n            case IconSize.NineX:\n                return NineX\n            default:\n                return Default\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/Shell/OverlayView.tsx",
    "content": "/**\n * OverlayView.ts\n *\n * React component responsible for showing / rendering overlays\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport { StackLayer } from \"../components/common\"\nimport * as State from \"./ShellState\"\n\nexport interface IOverlaysViewProps {\n    overlays: State.IOverlay[]\n}\n\nexport class OverlaysView extends React.PureComponent<IOverlaysViewProps, {}> {\n    public render(): JSX.Element[] {\n        const overlays = this.props.overlays.map(overlay => {\n            return (\n                <StackLayer zIndex={3} key={overlay.id}>\n                    {overlay.contents}\n                </StackLayer>\n            )\n        })\n\n        return overlays\n    }\n}\n\nexport const mapStateToProps = (state: State.IState): IOverlaysViewProps => ({\n    overlays: Object.keys(state.overlays).map(k => state.overlays[k]),\n})\n\nexport const Overlays = connect(mapStateToProps)(OverlaysView)\n"
  },
  {
    "path": "browser/src/UI/Shell/Shell.tsx",
    "content": "/**\n * UI/index.tsx\n *\n * Root setup & state for the UI\n * - Top-level render function lives here\n */\n\nimport * as React from \"react\"\nimport * as ReactDOM from \"react-dom\"\nimport { connect, Provider } from \"react-redux\"\n\nimport { remote } from \"electron\"\n\nimport { bindActionCreators } from \"redux\"\nimport thunk from \"redux-thunk\"\n\nimport { ShellView } from \"./ShellView\"\n\nimport * as ActionCreators from \"./ShellActionCreators\"\nimport { reducer } from \"./ShellReducer\"\nimport * as State from \"./ShellState\"\n\nimport { Colors } from \"./../../Services/Colors\"\nimport { focusManager } from \"./../../Services/FocusManager\"\nimport { windowManager } from \"./../../Services/WindowManager\"\n\nimport { createStore } from \"./../../Redux\"\n\nconst defaultState = State.createDefaultState()\n\nexport const store = createStore(\"Shell\", reducer, defaultState, [thunk])\n\nexport const Actions: typeof ActionCreators = bindActionCreators(\n    ActionCreators as any,\n    store.dispatch,\n)\n\nconst browserWindow = remote.getCurrentWindow()\nbrowserWindow.on(\"enter-full-screen\", () => {\n    store.dispatch({ type: \"ENTER_FULL_SCREEN\" })\n})\n\nbrowserWindow.on(\"leave-full-screen\", () => {\n    store.dispatch({ type: \"LEAVE_FULL_SCREEN\" })\n})\n\nexport const activate = (): void => {\n    render(defaultState)\n}\n\nexport const initializeColors = (colors: Colors): void => {\n    const setColors = () => Actions.setColors(colors.getColors() as any)\n\n    colors.onColorsChanged.subscribe(() => {\n        setColors()\n    })\n\n    setColors()\n}\n\nconst ShellContainer = connect((state: State.IState) => ({\n    theme: state.colors,\n}))(ShellView)\n\nexport const render = (state: State.IState): void => {\n    const hostElement = document.getElementById(\"host\")\n\n    ReactDOM.render(\n        <Provider store={store}>\n            <ShellContainer windowManager={windowManager} />\n        </Provider>,\n        hostElement,\n    )\n}\n\n// Don't execute code that depends on DOM in unit-tests\n// tslint:disable-next-line\nif (global[\"window\"]) {\n    document.body.addEventListener(\"click\", () => focusManager.enforceFocus())\n\n    // This is necessary to prevent electron's default behaviour on drag and dropping\n    // which replaces the webContent aka the entire editor with the text, NOT Good\n    // also DO Not Stop Propagation as this breaks other drag drop functionality\n    document.addEventListener(\"dragover\", ev => {\n        ev.preventDefault()\n    })\n\n    document.addEventListener(\"dragenter\", ev => {\n        ev.preventDefault()\n    })\n\n    document.addEventListener(\"drop\", ev => {\n        ev.preventDefault()\n    })\n}\n"
  },
  {
    "path": "browser/src/UI/Shell/ShellActionCreators.ts",
    "content": "/**\n * ActionCreators.ts\n *\n * Action Creators are relatively simple - they are just a function that returns an `Action`\n *\n * For information on Action Creators, check out this link:\n * http://redux.js.org/docs/basics/Actions.html\n */\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\nimport { IThemeColors } from \"./../../Services/Themes\"\n\nimport * as Actions from \"./ShellActions\"\nimport * as State from \"./ShellState\"\n\nexport type DispatchFunction = (action: any) => void\nexport type GetStateFunction = () => State.IState\n\nexport const setHasFocus = (hasFocus: boolean) => {\n    return {\n        type: \"SET_HAS_FOCUS\",\n        payload: {\n            hasFocus,\n        },\n    }\n}\n\nexport const setLoadingComplete = () => {\n    document.body.classList.add(\"loaded\")\n\n    return {\n        type: \"SET_LOADING_COMPLETE\",\n    }\n}\n\nexport const setWindowTitle = (title: string) => {\n    document.title = title\n\n    return {\n        type: \"SET_WINDOW_TITLE\",\n        payload: {\n            title,\n        },\n    }\n}\n\nexport const setColors = (colors: IThemeColors) => ({\n    type: \"SET_COLORS\",\n    payload: {\n        colors,\n    },\n})\n\nexport const setViewport = (width: number, height: number) => ({\n    type: \"SET_VIEWPORT\",\n    payload: {\n        width,\n        height,\n    },\n})\n\nexport const showStatusBarItem = (\n    id: string,\n    contents: JSX.Element,\n    alignment?: State.StatusBarAlignment,\n    priority?: number,\n) => (dispatch: DispatchFunction, getState: GetStateFunction) => {\n    const currentStatusBarItem = getState().statusBar[id]\n\n    if (currentStatusBarItem) {\n        alignment = alignment || currentStatusBarItem.alignment\n        priority = priority || currentStatusBarItem.priority\n    }\n\n    dispatch({\n        type: \"STATUSBAR_SHOW\",\n        payload: {\n            id,\n            contents,\n            alignment,\n            priority,\n        },\n    })\n}\n\nexport const hideStatusBarItem = (id: string) => ({\n    type: \"STATUSBAR_HIDE\",\n    payload: {\n        id,\n    },\n})\n\nexport const showOverlay = (id: string, contents: JSX.Element): Actions.IOverlayShowAction => ({\n    type: \"OVERLAY_SHOW\",\n    payload: {\n        id,\n        contents,\n    },\n})\n\nexport const hideOverlay = (id: string): Actions.IOverlayHideAction => ({\n    type: \"OVERLAY_HIDE\",\n    payload: {\n        id,\n    },\n})\n\nexport function setConfigValue<K extends keyof IConfigurationValues>(\n    k: K,\n    v: IConfigurationValues[K],\n): Actions.ISetConfigurationValue<K> {\n    return {\n        type: \"SET_CONFIGURATION_VALUE\",\n        payload: {\n            key: k,\n            value: v,\n        },\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/Shell/ShellActions.ts",
    "content": "/**\n * Action.ts\n *\n * Actions are simple payloads of information that send data from oni to the redux store.\n *\n * For information on Actions, check out this link:\n * http://redux.js.org/docs/basics/Actions.html\n */\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\nimport { IThemeColors } from \"./../../Services/Themes\"\n\nimport { StatusBarAlignment } from \"./ShellState\"\n\nexport interface ISetHasFocusAction {\n    type: \"SET_HAS_FOCUS\"\n    payload: {\n        hasFocus: boolean\n    }\n}\n\nexport interface IEnterFullScreenAction {\n    type: \"ENTER_FULL_SCREEN\"\n}\n\nexport interface ILeaveFullScreenAction {\n    type: \"LEAVE_FULL_SCREEN\"\n}\n\nexport interface ISetLoadingCompleteAction {\n    type: \"SET_LOADING_COMPLETE\"\n}\n\nexport interface ISetWindowTitleAction {\n    type: \"SET_WINDOW_TITLE\"\n    payload: {\n        title: string\n    }\n}\n\nexport interface ISetColorsAction {\n    type: \"SET_COLORS\"\n    payload: {\n        colors: IThemeColors\n    }\n}\n\nexport interface IStatusBarShowAction {\n    type: \"STATUSBAR_SHOW\"\n    payload: {\n        id: string\n        contents: JSX.Element\n        alignment: StatusBarAlignment\n        priority: number\n    }\n}\n\nexport interface IStatusBarHideAction {\n    type: \"STATUSBAR_HIDE\"\n    payload: {\n        id: string\n    }\n}\n\nexport interface IOverlayShowAction {\n    type: \"OVERLAY_SHOW\"\n    payload: {\n        id: string\n        contents: JSX.Element\n    }\n}\n\nexport interface IOverlayHideAction {\n    type: \"OVERLAY_HIDE\"\n    payload: {\n        id: string\n    }\n}\n\nexport interface ISetConfigurationValue<K extends keyof IConfigurationValues> {\n    type: \"SET_CONFIGURATION_VALUE\"\n    payload: {\n        key: K\n        value: IConfigurationValues[K]\n    }\n}\n\nexport type Action<K extends keyof IConfigurationValues> = SimpleAction | ActionWithGeneric<K>\n\nexport type SimpleAction =\n    | IEnterFullScreenAction\n    | ILeaveFullScreenAction\n    | ISetColorsAction\n    | IOverlayShowAction\n    | IOverlayHideAction\n    | IStatusBarHideAction\n    | IStatusBarShowAction\n    | ISetHasFocusAction\n    | ISetLoadingCompleteAction\n    | ISetWindowTitleAction\n\nexport type ActionWithGeneric<K extends keyof IConfigurationValues> = ISetConfigurationValue<K>\n"
  },
  {
    "path": "browser/src/UI/Shell/ShellReducer.ts",
    "content": "/**\n * Reducer.ts\n *\n * Top-level reducer for UI state transforms\n */\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\n\nimport * as Actions from \"./ShellActions\"\nimport * as State from \"./ShellState\"\n\nexport function reducer<K extends keyof IConfigurationValues>(\n    s: State.IState,\n    a: Actions.Action<K>,\n) {\n    if (!s) {\n        return s\n    }\n\n    switch (a.type) {\n        case \"ENTER_FULL_SCREEN\":\n            return {\n                ...s,\n                isFullScreen: true,\n            }\n        case \"LEAVE_FULL_SCREEN\":\n            return {\n                ...s,\n                isFullScreen: false,\n            }\n        case \"SET_HAS_FOCUS\":\n            return {\n                ...s,\n                hasFocus: a.payload.hasFocus,\n            }\n        case \"SET_LOADING_COMPLETE\":\n            return {\n                ...s,\n                isLoaded: true,\n            }\n        case \"SET_WINDOW_TITLE\":\n            return {\n                ...s,\n                windowTitle: a.payload.title,\n            }\n        case \"SET_COLORS\":\n            return {\n                ...s,\n                colors: a.payload.colors,\n            }\n        case \"SET_CONFIGURATION_VALUE\":\n            const obj: Partial<IConfigurationValues> = {}\n            obj[a.payload.key] = a.payload.value\n            const newConfig = { ...s.configuration, ...obj }\n            return {\n                ...s,\n                configuration: newConfig,\n            }\n        default:\n            return {\n                ...s,\n                overlays: overlaysReducer(s.overlays, a),\n                statusBar: statusBarReducer(s.statusBar, a),\n            }\n    }\n}\n\nexport const overlaysReducer = (s: State.Overlays, a: Actions.SimpleAction) => {\n    switch (a.type) {\n        case \"OVERLAY_SHOW\":\n            return {\n                ...s,\n                [a.payload.id]: {\n                    id: a.payload.id,\n                    contents: a.payload.contents,\n                },\n            }\n        case \"OVERLAY_HIDE\":\n            const newState = {\n                ...s,\n            }\n\n            delete newState[a.payload.id]\n            return newState\n        default:\n            return s\n    }\n}\n\nexport const statusBarReducer = (s: State.StatusBar, a: Actions.SimpleAction) => {\n    switch (a.type) {\n        case \"STATUSBAR_SHOW\":\n            const existingItem = s[a.payload.id] || {}\n            const newItem = {\n                ...existingItem,\n                ...a.payload,\n            }\n\n            return {\n                ...s,\n                [a.payload.id]: newItem,\n            }\n        case \"STATUSBAR_HIDE\":\n            return {\n                ...s,\n                [a.payload.id]: null,\n            }\n        default:\n            return s\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/Shell/ShellState.ts",
    "content": "/**\n * State.ts\n *\n * This file describes the Redux state of the app\n */\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { IConfigurationValues } from \"./../../Services/Configuration\"\nimport { DefaultThemeColors, IThemeColors } from \"./../../Services/Themes\"\n\nexport interface Errors {\n    [file: string]: { [key: string]: types.Diagnostic[] }\n}\n\n/**\n * Viewport encompasses the actual 'app' height\n */\nexport interface IViewport {\n    width: number\n    height: number\n}\n\nexport interface IToolTip {\n    id: string\n    options: Oni.ToolTip.ToolTipOptions\n    element: JSX.Element\n}\n\nexport interface StatusBar {\n    [key: string]: IStatusBarItem\n}\nexport interface Overlays {\n    [key: string]: IOverlay\n}\n\nexport interface IState {\n    // Editor\n    hasFocus: boolean\n    isFullScreen: boolean\n    configuration: IConfigurationValues\n\n    // Shell\n    isLoaded: boolean\n    colors: IThemeColors\n    windowTitle: string\n\n    statusBar: { [id: string]: IStatusBarItem }\n    overlays: { [id: string]: IOverlay }\n\n    errors: Errors\n}\n\nexport interface IOverlay {\n    id: string\n    contents: JSX.Element\n}\n\nexport enum StatusBarAlignment {\n    Left,\n    Right,\n}\n\nexport interface IStatusBarItem {\n    alignment: StatusBarAlignment\n    contents: JSX.Element\n    priority: number\n    visible: boolean\n}\n\nexport function readConf<K extends keyof IConfigurationValues>(\n    conf: IConfigurationValues,\n    k: K,\n): IConfigurationValues[K] {\n    if (!conf) {\n        return null\n    } else {\n        return conf[k]\n    }\n}\n\nexport const createDefaultState = (): IState => ({\n    hasFocus: false,\n    colors: DefaultThemeColors,\n    isLoaded: false,\n    isFullScreen: false,\n\n    configuration: {} as IConfigurationValues,\n\n    errors: {},\n    overlays: {},\n    statusBar: {},\n    windowTitle: \"\",\n})\n"
  },
  {
    "path": "browser/src/UI/Shell/ShellView.tsx",
    "content": "/**\n * ShellView is the root UI / React component\n */\n\nimport * as React from \"react\"\n\nimport { Provider } from \"react-redux\"\n\nimport * as Platform from \"./../../Platform\"\n\nimport { focusManager } from \"./../../Services/FocusManager\"\nimport { inputManager } from \"./../../Services/InputManager\"\nimport { IThemeColors } from \"./../../Services/Themes/ThemeManager\"\nimport * as WindowManager from \"./../../Services/WindowManager\"\n\nimport { Background } from \"./../components/Background\"\nimport { ThemeProvider } from \"./../components/common\"\nimport { Loading } from \"./../components/Loading\"\nimport StatusBar from \"./../components/StatusBar\"\n\nimport { WindowSplits } from \"./../components/WindowSplits\"\nimport { WindowTitle } from \"./../components/WindowTitle\"\n\nimport { Overlays } from \"./OverlayView\"\n\ninterface IShellViewComponentProps {\n    theme: IThemeColors\n    windowManager: WindowManager.WindowManager\n}\n\nconst titleBarVisible = Platform.isMac()\n\ninterface IShellViewState {\n    /**\n     * Tracks if composition is occurring (ie, an IME is active)\n     */\n    isComposing: boolean\n}\n\nexport class ShellView extends React.PureComponent<IShellViewComponentProps, IShellViewState> {\n    constructor(props: IShellViewComponentProps) {\n        super(props)\n\n        this.state = {\n            isComposing: false,\n        }\n    }\n\n    public render() {\n        return (\n            <ThemeProvider theme={this.props.theme}>\n                <div\n                    className=\"stack disable-mouse\"\n                    onKeyDownCapture={evt => this._onRootKeyDown(evt)}\n                    onCompositionEndCapture={evt => this._onCompositionEnd(evt)}\n                    onCompositionStartCapture={evt => this._onCompositionStart(evt)}\n                >\n                    <div className=\"stack\">\n                        <Background />\n                    </div>\n                    <div className=\"stack\">\n                        <div className=\"container vertical full\">\n                            <div className=\"container fixed\">\n                                <WindowTitle visible={titleBarVisible} />\n                            </div>\n                            <div className=\"container full\">\n                                <div className=\"stack\">\n                                    <Provider store={this.props.windowManager.store}>\n                                        <WindowSplits windowManager={this.props.windowManager} />\n                                    </Provider>\n                                </div>\n                                <Overlays />\n                            </div>\n                            <div className=\"container fixed layer\">\n                                <StatusBar />\n                            </div>\n                        </div>\n                    </div>\n                    <Loading />\n                </div>\n            </ThemeProvider>\n        )\n    }\n\n    private _onRootKeyDown(evt: React.KeyboardEvent<HTMLElement>): void {\n        // onCompositionStart can't detect composing mode for the first character\n        // because it is fired after onKeyDown.\n        // keyCode is deprecated but it seems this is the only method to detect\n        // composing mode for the first character for now.\n        let isComposing = false\n        if (evt.keyCode === 229) {\n            isComposing = true\n        }\n        const vimKey = inputManager.resolvers.resolveKeyEvent(evt.nativeEvent)\n        if (!this.state.isComposing && !isComposing && inputManager.handleKey(vimKey)) {\n            evt.stopPropagation()\n            evt.preventDefault()\n        } else {\n            focusManager.enforceFocus()\n        }\n    }\n\n    private _onCompositionStart(evt: React.CompositionEvent<HTMLElement>) {\n        this.setState({\n            isComposing: true,\n        })\n    }\n\n    private _onCompositionEnd(evt: React.CompositionEvent<HTMLElement>) {\n        this.setState({\n            isComposing: false,\n        })\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/Shell/index.ts",
    "content": "export * from \"./Shell\"\n"
  },
  {
    "path": "browser/src/UI/components/Arrow.less",
    "content": "@import (reference) \"./common.less\";\n\n.arrow {\n    animation-duration: 0.3s;\n    animation-delay: 0.2s;\n    opacity: 0;\n    animation-fill-mode: forwards;\n\n    &.right {\n        animation-name: appear-right;\n    }\n\n    &.left {\n        animation-name: appear-left;\n    }\n\n    &.down {\n        animation-name: appear-down;\n    }\n\n    &.up {\n        animation-name: appear-up;\n    }\n}\n\n@keyframes appear-down {\n    from {\n        transform: translateY(-4px);\n        opacity: 0;\n    }\n    to {\n        transform: translateY(0px);\n        opacity: 1;\n    }\n}\n@keyframes appear-up {\n    from {\n        transform: translateY(4px);\n        opacity: 0;\n    }\n    to {\n        transform: translateY(0px);\n        opacity: 1;\n    }\n}\n@keyframes appear-left {\n    from {\n        transform: translateX(4px);\n        opacity: 0;\n    }\n    to {\n        transform: translateX(0px);\n        opacity: 1;\n    }\n}\n@keyframes appear-right {\n    from {\n        transform: translateX(-4px);\n        opacity: 0;\n    }\n    to {\n        transform: translateX(0px);\n        opacity: 1;\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/Arrow.tsx",
    "content": "/**\n * Arrow.tsx\n *\n * Simple 'up' or 'down' arrow component\n */\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\nimport { css } from \"./common\"\n\nexport enum ArrowDirection {\n    Up = 0,\n    Down = 1,\n    Left = 2,\n    Right = 3,\n}\n\nexport interface IArrowProps {\n    size: number\n    direction: ArrowDirection\n    color?: string\n    isSelected?: boolean\n}\n\nconst transparentBorder = (props: IArrowProps) => `${props.size * 0.8}px solid transparent`\nconst solidBorder = (props: IArrowProps) => `${props.size}px solid ${props.color}`\n\nconst getArrowColor = (props: { isSelected: boolean; color: string; theme: any }) => {\n    return props.isSelected\n        ? props.theme[\"contextMenu.highlight\"]\n        : props.color\n            ? props.color\n            : \"transparent\"\n}\n\nconst getDirectionStyles = (props: IArrowProps): string => {\n    const color = css`\n        color: ${getArrowColor};\n    `\n\n    switch (props.direction) {\n        case ArrowDirection.Up:\n            return `\n                ${color};\n                width: 0px;\n                height: 0px;\n                border-left: ${transparentBorder(props)};\n                border-right: ${transparentBorder(props)};\n                border-bottom: ${solidBorder(props)};\n            `\n        case ArrowDirection.Down:\n            return `\n                ${color};\n                width: 0px;\n                height: 0px;\n                border-left: ${transparentBorder(props)};\n                border-right: ${transparentBorder(props)};\n                border-top: ${solidBorder(props)};\n            `\n        case ArrowDirection.Left:\n            return `\n                ${color};\n                width: 0px;\n                height: 0px;\n                border-top: ${transparentBorder(props)};\n                border-right: ${solidBorder(props)};\n                border-bottom: ${transparentBorder(props)};\n            `\n        case ArrowDirection.Right:\n            return `\n                ${color};\n                width: 0px;\n                height: 0px;\n                border-top: ${transparentBorder(props)};\n                border-left: ${solidBorder(props)};\n                border-bottom: ${transparentBorder(props)};\n            `\n        default:\n            return `${color};`\n    }\n}\nexport const Arrow = styled<IArrowProps, \"div\">(\"div\")`\n    ${getDirectionStyles};\n`\n\nexport const preview = () => {\n    return <Arrow size={100} color=\"yellow\" direction={ArrowDirection.Left} />\n}\n"
  },
  {
    "path": "browser/src/UI/components/Background.tsx",
    "content": "import * as React from \"react\"\n\nimport { connect } from \"react-redux\"\nimport * as State from \"./../Shell/ShellState\"\n\nimport styled from \"styled-components\"\nimport { withProps } from \"./common\"\n\nexport interface IBackgroundProps {\n    backgroundColor: string\n    backgroundImageUrl: string\n    backgroundImageSize: string\n    backgroundOpacity: number\n}\n\nexport const BackgroundImageView = withProps<IBackgroundProps>(styled.div)`\n    background-image: url(\"${props => props.backgroundImageUrl}\");\n    background-size: ${props => props.backgroundImageSize || \"cover\"};\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    `\n\nexport const BackgroundColorView = withProps<IBackgroundProps>(styled.div)`\n    background-color: ${props => props.backgroundColor};\n    opacity: ${props => props.backgroundOpacity};\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    `\n\nexport const BackgroundView = (props: IBackgroundProps) => (\n    <div>\n        {props.backgroundImageUrl ? <BackgroundImageView {...props} /> : null}\n        <BackgroundColorView {...props} />\n    </div>\n)\n\nconst mapStateToProps = (state: State.IState): IBackgroundProps => {\n    const conf = state.configuration\n    return {\n        backgroundColor: state.colors.background,\n        backgroundImageUrl: State.readConf(conf, \"editor.backgroundImageUrl\"),\n        backgroundImageSize: State.readConf(conf, \"editor.backgroundImageSize\"),\n        backgroundOpacity: State.readConf(conf, \"editor.backgroundOpacity\"),\n    }\n}\n\nexport const Background = connect(mapStateToProps)(BackgroundView)\n"
  },
  {
    "path": "browser/src/UI/components/BufferLayerHeader.tsx",
    "content": "/**\n * BufferLayerHeader.tsx\n *\n * Common header used by several buffer layers\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nconst HeaderWrapper = styled.div`\n    padding: 1em;\n`\n\nconst PrimaryHeader = styled.div`\n    font-size: 2em;\n    font-weight: bold;\n`\n\nconst SubHeader = styled.div`\n    font-size: 1.2em;\n`\n\nexport interface BufferLayerHeaderProps {\n    title: string\n    description: string\n}\n\nexport const BufferLayerHeader = (props: BufferLayerHeaderProps) => {\n    return (\n        <HeaderWrapper>\n            <PrimaryHeader>{props.title}</PrimaryHeader>\n            <SubHeader>{props.description}</SubHeader>\n        </HeaderWrapper>\n    )\n}\n"
  },
  {
    "path": "browser/src/UI/components/BufferScrollBar.tsx",
    "content": "import * as React from \"react\"\n\nimport * as uniqBy from \"lodash/uniqBy\"\nimport styled from \"styled-components\"\nimport { bufferScrollBarSize, pixel, withProps } from \"./common\"\n\nimport { editorManager } from \"./../../Services/EditorManager\"\n\nexport interface IBufferScrollBarProps {\n    windowId: number\n    bufferSize: number\n    height: number\n    windowTopLine: number\n    windowBottomLine: number\n    markers: IScrollBarMarker[]\n    visible: boolean\n}\n\nexport interface IBufferScrollBarState {\n    scrollBarTop: number\n}\n\nexport interface IScrollBarMarker {\n    line: number\n    height: number\n    color: string\n}\n\nconst ScrollBarContainer = withProps<Partial<IScrollBarWindow>>(styled.div).attrs({\n    style: ({ height }: Partial<IScrollBarWindow>) => ({\n        height: pixel(height),\n    }),\n})`\n    position: fixed;\n    top: 0px;\n    bottom: 0px;\n    right: 0px;\n    background-color: rgba(0, 0, 0, 0.2);\n    width: ${bufferScrollBarSize};\n    border-bottom: 1px solid black;\n    pointer-events: auto;\n`\ninterface IScrollBarWindow {\n    height: number\n    top: number\n}\n\nconst ScrollBarWindow = withProps<IScrollBarWindow>(styled.div).attrs({\n    style: ({ top, height }: IScrollBarWindow) => ({\n        top: pixel(top),\n        height: pixel(height),\n    }),\n})`\n    position: absolute;\n    width: ${bufferScrollBarSize};\n    background-color: rgba(200, 200, 200, 0.2);\n    border-top: 1px solid rgba(255, 255, 255, 0.1);\n    border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n    pointer-events: none;\n`\ninterface IMarkerElement {\n    height: string\n    top: number\n    color: string\n}\n\nexport const MarkerElement = withProps<IMarkerElement>(styled.div).attrs({\n    style: ({ height, top }: IMarkerElement) => ({\n        top: pixel(top),\n        height,\n    }),\n})`\n        background-color: ${p => p.color};\n        width: 100%;\n        position: absolute;\n        pointer-events: none;\n`\n\nexport class BufferScrollBar extends React.PureComponent<\n    IBufferScrollBarProps,\n    IBufferScrollBarState\n> {\n    public static defaultProps: Partial<IBufferScrollBarProps> = {\n        markers: [],\n    }\n\n    public state: IBufferScrollBarState = {\n        scrollBarTop: 0,\n    }\n\n    public setLine = (y: number) => {\n        const lineFraction = Math.min(\n            Math.max((y - this.state.scrollBarTop) / this.props.height, 0),\n            1,\n        )\n        const newLine = Math.ceil(editorManager.activeEditor.activeBuffer.lineCount * lineFraction)\n        editorManager.activeEditor.activeBuffer.setCursorPosition(newLine, 0)\n    }\n\n    public beginScroll = (e: React.MouseEvent<HTMLDivElement>) => {\n        e.preventDefault()\n        // offsetY is definitely on the scrollbar in the beginning of the click\n        this.setState({ scrollBarTop: e.nativeEvent.clientY - e.nativeEvent.offsetY })\n        this.setLine(e.nativeEvent.clientY)\n        document.addEventListener(\"mousemove\", this.trackScroll, true)\n        document.addEventListener(\"mouseup\", this.endScroll, true)\n    }\n\n    public trackScroll = (e: MouseEvent) => {\n        e.preventDefault()\n        this.setLine(e.clientY)\n    }\n\n    public endScroll = (e: MouseEvent) => {\n        e.preventDefault()\n        this.setLine(e.clientY)\n        document.removeEventListener(\"mousemove\", this.trackScroll, true)\n        document.removeEventListener(\"mouseup\", this.endScroll, true)\n    }\n\n    public calculateWindowDimensions() {\n        const { windowBottomLine, windowTopLine, bufferSize, height } = this.props\n        const windowHeight = (windowBottomLine - windowTopLine + 1) / bufferSize * height\n        const windowTop = (windowTopLine - 1) / bufferSize * height\n        return { windowHeight, windowTop }\n    }\n\n    public renderMarkers() {\n        // Only show one marker per line in the scroll bar\n        const uniqueMarkers = uniqBy(this.props.markers, ({ line }) => line)\n        const markerElements = uniqueMarkers.map(({ line, color }) => {\n            const pos = line / this.props.bufferSize * this.props.height\n            const size = \"2px\"\n\n            return (\n                <MarkerElement\n                    top={pos}\n                    height={size}\n                    color={color}\n                    id=\"scrollbar-marker-element\"\n                    key={`${this.props.windowId}_${color}_${line}`}\n                />\n            )\n        })\n        return markerElements\n    }\n\n    public render() {\n        if (!this.props.visible) {\n            return null\n        }\n\n        const markerElements = this.renderMarkers()\n        const { windowHeight, windowTop } = this.calculateWindowDimensions()\n\n        return (\n            <ScrollBarContainer\n                key={this.props.windowId}\n                height={this.props.height}\n                onMouseDown={this.beginScroll}\n            >\n                <ScrollBarWindow top={windowTop} height={windowHeight} />\n                {markerElements}\n            </ScrollBarContainer>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/Caret.tsx",
    "content": "import * as React from \"react\"\n\nconst Caret = ({ active }: { active: boolean }) => {\n    const caretStyle = {\n        transform: active ? \"rotateZ(45deg)\" : \"rotateZ(0deg)\",\n        transition: \"transform 0.1s ease-in\",\n    }\n\n    return <i style={caretStyle} className=\"fa fa-caret-right\" />\n}\n\nexport default Caret\n"
  },
  {
    "path": "browser/src/UI/components/CodeActions.tsx",
    "content": "/**\n * CodeActions.tsx\n *\n * Components used for rendering when code actions are available\n */\n\nimport * as React from \"react\"\n\nimport { commandManager } from \"./../../Services/CommandManager\"\nimport { QuickInfoDocumentation } from \"./../../UI/components/QuickInfo\"\n\nimport { Icon, IconSize } from \"./../Icon\"\n\n/**\n * Helper component to render errors in the QuickInfo bubble\n */\nexport class CodeActionHover extends React.PureComponent<{}, {}> {\n    public render(): null | JSX.Element {\n        const style: React.CSSProperties = {\n            padding: \"1em\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            cursor: \"pointer\",\n        }\n\n        return (\n            <div className=\"container horizontal quickinfo-container\">\n                <div\n                    className=\"container horizontal fixed\"\n                    style={style}\n                    onClick={() => commandManager.executeCommand(\"language.codeAction.expand\")}\n                >\n                    <Icon name=\"lightbulb-o\" size={IconSize.Large} />\n                </div>\n                <div className=\"container full quickinfo\">\n                    <div className=\"title\">Refactorings available</div>\n                    <QuickInfoDocumentation text=\"Press alt-enter to expand\" />\n                </div>\n            </div>\n        )\n    }\n}\n\nexport const renderCodeActionHover = () => <CodeActionHover />\n"
  },
  {
    "path": "browser/src/UI/components/CommandLine.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport styled from \"styled-components\"\n\nimport { Icon } from \"./../../UI/Icon\"\nimport { fadeInAndDown } from \"./animations\"\nimport { boxShadow } from \"./common\"\n\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nconst CommandLineBox = styled<{ visible: boolean }, \"div\">(\"div\")`\n    ${p => !p.visible && `visibility: hidden`};\n    position: relative;\n    margin-top: 16px;\n    padding: 8px;\n    width: 75%;\n    max-width: 900px;\n    background-color: ${p => p.theme[\"menu.background\"]};\n    ${boxShadow};\n    animation: ${fadeInAndDown} 0.08s ease-in;\n    box-sizing: border-box;\n    overflow-wrap: break-word;\n`\nconst CommandLineOutput = styled.div`\n    white-space: pre-wrap; /* CRUCIAL to render white-space correctly */\n    position: relative;\n    border: 0px;\n    background-color: rgba(0, 0, 0, 0.2);\n    font-size: 1.1em;\n    box-sizing: border-box;\n    width: 100%;\n    height: auto;\n    padding: 8px;\n    outline: none;\n    color: white;\n`\n\nconst Cursor = styled.span`\n    background-color: white;\n    width: 2px;\n    position: absolute;\n    bottom: 6px;\n    height: 1.3em;\n`\n\nconst ArrowContainer = styled.span`\n    font-size: 0.7em;\n    margin-right: 0.6em;\n`\n\nexport interface ICommandLineRendererProps {\n    showIcons: boolean\n    visible: boolean\n    content: string\n    position: number\n    firstchar: string\n    level: number\n    prompt: string\n}\n\ninterface State {\n    focused: boolean\n}\n\nexport const CommandLineIcon = (props: { iconName: string; arrow?: boolean }) => (\n    <span>\n        {!props.arrow ? (\n            <Icon name={props.iconName} />\n        ) : (\n            <ArrowContainer>\n                <Icon name={props.iconName} />\n            </ArrowContainer>\n        )}\n    </span>\n)\n\nexport class CommandLine extends React.PureComponent<ICommandLineRendererProps, State> {\n    public state = {\n        focused: false,\n    }\n\n    private _inputElement: HTMLInputElement\n\n    public componentWillReceiveProps(nextProps: ICommandLineRendererProps) {\n        if (!this.state.focused && nextProps.visible) {\n            this.setState({ focused: true })\n        }\n    }\n\n    public renderIconOrChar(character: string) {\n        if (!this.props.showIcons) {\n            return character\n        }\n        switch (character) {\n            case \"/\":\n                return [\n                    <CommandLineIcon iconName=\"search\" key={`${character}-search`} />,\n                    <CommandLineIcon\n                        arrow\n                        iconName=\"arrow-right\"\n                        key={`${character}-arrow-right`}\n                    />,\n                ]\n            case \"?\":\n                return [\n                    <CommandLineIcon iconName=\"search\" key={`${character}-search`} />,\n                    <CommandLineIcon key={`${character}-arrow-left`} arrow iconName=\"arrow-left\" />,\n                ]\n            default:\n                return character\n        }\n    }\n\n    public getCommandLineSections() {\n        const { content, position } = this.props\n        if (content) {\n            const segments = content.split(\"\")\n            const beginning = segments.slice(0, position)\n            const end = segments.slice(position)\n            return { beginning, end }\n        }\n        return null\n    }\n\n    public render(): null | JSX.Element {\n        const { visible, firstchar } = this.props\n        const { focused } = this.state\n\n        if (!focused && visible && this._inputElement) {\n            this._inputElement.focus()\n        }\n\n        const segments = this.getCommandLineSections()\n\n        return (\n            <CommandLineBox visible={visible} className=\"command-line\">\n                <CommandLineOutput\n                    innerRef={e => (this._inputElement = e)}\n                    className=\"command-line-output\"\n                >\n                    {this.renderIconOrChar(firstchar)}\n                    {this.props.prompt}\n                    {segments && segments.beginning}\n                    <Cursor />\n                    {segments && segments.end}\n                </CommandLineOutput>\n            </CommandLineBox>\n        )\n    }\n}\n\nconst mapStateToProps = ({ commandLine, configuration }: State.IState) => {\n    const { visible, position, content, firstchar, level, prompt } = commandLine\n    return {\n        showIcons: configuration[\"commandline.icons\"],\n        visible,\n        content,\n        firstchar,\n        position,\n        level,\n        prompt,\n    }\n}\n\nexport default connect<ICommandLineRendererProps>(mapStateToProps)(CommandLine)\n"
  },
  {
    "path": "browser/src/UI/components/Cursor.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport styled from \"styled-components\"\n\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nimport { Motion, spring } from \"react-motion\"\n\nimport { TypingPredictionManager } from \"./../../Services/TypingPredictionManager\"\n\nimport { addDefaultUnitIfNeeded } from \"./../../Font\"\n\nexport interface ICursorRendererProps {\n    animated: boolean\n    x: number\n    y: number\n    scale: number\n    width: number\n    height: number\n    mode: string\n    color: string\n    textColor: string\n    character: string\n    fontFamily: string\n    fontSize: string\n    fontPixelWidth: number\n    visible: boolean\n\n    typingPrediction: TypingPredictionManager\n}\n\nconst StyledCursor = styled.div``\n\nexport interface ICursorRendererState {\n    predictedCursorColumn: number\n}\n\nclass CursorRenderer extends React.PureComponent<ICursorRendererProps, ICursorRendererState> {\n    constructor(props: ICursorRendererProps) {\n        super(props)\n\n        this.state = {\n            predictedCursorColumn: -1,\n        }\n    }\n\n    public componentDidMount(): void {\n        this.props.typingPrediction.onPredictionsChanged.subscribe(predictions => {\n            this.setState({\n                predictedCursorColumn: predictions.predictedCursorColumn,\n            })\n        })\n    }\n\n    public render(): JSX.Element {\n        const fontFamily = this.props.fontFamily\n        const fontSize = this.props.fontSize\n\n        const isInsertCursor = this.props.mode === \"insert\" || this.props.mode === \"cmdline_normal\"\n        const height = this.props.height ? this.props.height.toString() + \"px\" : \"0px\"\n        const width = isInsertCursor ? 0 : this.props.width\n        const characterToShow = isInsertCursor ? \"\" : this.props.character\n\n        const position =\n            this.props.mode === \"insert\" && this.state.predictedCursorColumn >= 0\n                ? this.state.predictedCursorColumn * this.props.fontPixelWidth\n                : this.props.x\n\n        const containerStyle: React.CSSProperties = {\n            visibility: this.props.visible ? \"visible\" : \"hidden\",\n            position: \"absolute\",\n            left: (position - 1).toString() + \"px\",\n            top: this.props.y.toString() + \"px\",\n            width: (width + 2).toString() + \"px\",\n            height,\n            lineHeight: height,\n            color: this.props.textColor,\n            fontFamily,\n            fontSize,\n            transform: \"translateZ(0px)\",\n        }\n\n        const innerPositionStyle: React.CSSProperties = {\n            position: \"absolute\",\n            left: \"0px\",\n            right: \"0px\",\n            bottom: \"0px\",\n            top: \"0px\",\n        }\n\n        const cursorBlockStyle: React.CSSProperties = {\n            ...innerPositionStyle,\n            backgroundColor: this.props.color,\n        }\n\n        const cursorCharacterStyle: React.CSSProperties = {\n            ...innerPositionStyle,\n            textAlign: \"center\",\n            color: this.props.textColor,\n        }\n\n        if (!this.props.animated) {\n            return this._renderCursor(\n                containerStyle,\n                cursorBlockStyle,\n                cursorCharacterStyle,\n                characterToShow,\n            )\n        } else {\n            return (\n                <Motion\n                    defaultStyle={{ scale: 0 }}\n                    style={{ scale: spring(this.props.scale, { stiffness: 120, damping: 8 }) }}\n                >\n                    {val => {\n                        const cursorStyle = {\n                            ...cursorBlockStyle,\n                            transform: \"scale(\" + val.scale + \")\",\n                        }\n                        return this._renderCursor(\n                            containerStyle,\n                            cursorStyle,\n                            cursorCharacterStyle,\n                            characterToShow,\n                        )\n                    }}\n                </Motion>\n            )\n        }\n    }\n\n    private _renderCursor(\n        containerStyle: React.CSSProperties,\n        cursorBlockStyle: React.CSSProperties,\n        cursorCharacterStyle: React.CSSProperties,\n        characterToShow: string,\n    ): JSX.Element {\n        return (\n            <StyledCursor style={containerStyle} className=\"cursor\">\n                <div style={cursorBlockStyle} />\n                <div style={cursorCharacterStyle}>{characterToShow}</div>\n            </StyledCursor>\n        )\n    }\n}\n\nexport interface ICursorProps {\n    typingPrediction: TypingPredictionManager\n}\n\nconst mapStateToProps = (state: State.IState, props: ICursorProps): ICursorRendererProps => {\n    return {\n        ...props,\n        animated: State.readConf(state.configuration, \"ui.animations.enabled\"),\n        x: state.cursorPixelX, // + state.typingPredictions.length * state.cursorPixelWidth,\n        y: state.cursorPixelY,\n        scale: state.mode === \"operator\" ? 0.8 : state.cursorScale,\n        width: state.cursorPixelWidth,\n        height: state.fontPixelHeight,\n        mode: state.mode,\n        color: state.colors[\"editor.foreground\"],\n        textColor: state.colors[\"editor.background\"],\n        character: state.cursorCharacter,\n        fontPixelWidth: state.fontPixelWidth,\n        fontFamily: State.readConf(state.configuration, \"editor.fontFamily\"),\n        fontSize: addDefaultUnitIfNeeded(State.readConf(state.configuration, \"editor.fontSize\")),\n        visible: !state.imeActive,\n    }\n}\n\nexport const Cursor = connect(mapStateToProps)(CursorRenderer)\n"
  },
  {
    "path": "browser/src/UI/components/CursorLine.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport * as Selectors from \"./../../Editor/NeovimEditor/NeovimEditorSelectors\"\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nexport interface ICursorLineRendererProps {\n    x: number\n    y: number\n    width: number\n    height: number\n    color: string\n    visible: boolean\n    opacity: number\n}\n\nexport interface ICursorLineProps {\n    lineType: string\n}\n\nclass CursorLineRenderer extends React.PureComponent<ICursorLineRendererProps, {}> {\n    public render(): null | JSX.Element {\n        if (!this.props.visible) {\n            return null\n        }\n\n        const width = this.props.width\n\n        const cursorStyle: React.CSSProperties = {\n            position: \"absolute\",\n            left: this.props.x.toString() + \"px\", // Window Start\n            top: this.props.y.toString() + \"px\", // Same as cursor\n            width: width.toString() + \"px\", // Window width\n\n            height: this.props.height ? this.props.height.toString() + \"px\" : \"0px\", // Same as cursor\n            backgroundColor: this.props.color,\n            opacity: this.props.opacity,\n        }\n\n        return <div style={cursorStyle} className=\"cursorLine\" />\n    }\n}\n\nconst emptyProps: ICursorLineRendererProps = {\n    x: 0,\n    y: 0,\n    width: 0,\n    height: 0,\n    color: null,\n    visible: false,\n    opacity: 0,\n}\n\nconst mapStateToProps = (state: State.IState, props: ICursorLineProps) => {\n    const opacitySetting =\n        props.lineType === \"line\" ? \"editor.cursorLineOpacity\" : \"editor.cursorColumnOpacity\"\n    const opacity = state.configuration[opacitySetting]\n\n    const enabledSetting = props.lineType === \"line\" ? \"editor.cursorLine\" : \"editor.cursorColumn\"\n    const enabled = state.configuration[enabledSetting]\n\n    const isNormalInsertOrVisualMode =\n        state.mode === \"normal\" || state.mode === \"insert\" || state.mode === \"visual\"\n    const visible = enabled && isNormalInsertOrVisualMode\n\n    if (!visible) {\n        return emptyProps\n    }\n\n    const activeWindowDimensions = Selectors.getActiveWindowPixelDimensions(state)\n\n    return {\n        x: props.lineType === \"line\" ? activeWindowDimensions.x : state.cursorPixelX,\n        y: props.lineType === \"line\" ? state.cursorPixelY : activeWindowDimensions.y,\n        width: props.lineType === \"line\" ? activeWindowDimensions.width : state.cursorPixelWidth,\n        height: props.lineType === \"line\" ? state.fontPixelHeight : activeWindowDimensions.height,\n        color: state.colors[\"editore.foreground\"],\n        visible,\n        opacity,\n    }\n}\n\nexport const CursorLine = connect(mapStateToProps)(CursorLineRenderer)\n"
  },
  {
    "path": "browser/src/UI/components/CursorPositioner.tsx",
    "content": "/**\n * CursorPositioner.tsx\n *\n * Helper component to position items around the cursor.\n * Measures the rendered element and adjusts positioning as needed.\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport * as Oni from \"oni-api\"\n\nimport { IState } from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nimport { Arrow, ArrowDirection } from \"./Arrow\"\nimport styled, { pixel, withProps } from \"./common\"\n\nexport enum OpenDirection {\n    Up = 1,\n    Down = 2,\n}\n\nexport interface ICursorPositionerProps {\n    position?: Oni.Coordinates.PixelSpacePoint\n    beakColor?: string\n    openDirection?: OpenDirection\n    hideArrow?: boolean\n    key?: string\n}\n\nexport interface ICursorPositionerViewProps extends ICursorPositionerProps {\n    x: number\n    y: number\n    lineHeight: number\n\n    containerWidth: number\n    containerHeight: number\n\n    fontPixelWidth: number\n\n    backgroundColor: string\n}\n\ninterface ContainerProps {\n    adjustedY: number\n    containerWidth: number\n    isMeasured: boolean\n}\n\ninterface ArrowContainerProps {\n    x: number\n    fontPixelWidth: number\n    hideArrow: boolean\n    shouldOpenDownwards: boolean\n}\n\ninterface ChildProps {\n    adjustedX: number\n    isFullWidth: boolean\n    shouldOpenDownwards: boolean\n}\n\ntype VisibilityProperty = \"hidden\" | \"visible\"\n\nconst PositionerContainer = withProps<ContainerProps>(styled.div).attrs({\n    style: ({ adjustedY, containerWidth, isMeasured }: ContainerProps) => ({\n        top: pixel(adjustedY),\n        width: pixel(containerWidth),\n        // Wait until we've measured the bounds to show..\n        visibility: (isMeasured ? \"visible\" : \"hidden\") as VisibilityProperty,\n    }),\n})`\n    position: absolute;\n    left: 0px;\n    max-width: 45vw;\n`\n\nconst openFromBottomStyle = { bottom: \"0px\" }\nconst openFromTopStyle = { top: \"0px\" }\n\nconst PositionerChild = withProps<ChildProps>(styled.div).attrs({\n    style: (props: ChildProps) => ({\n        ...(props.shouldOpenDownwards ? openFromTopStyle : openFromBottomStyle),\n        left: props.isFullWidth ? \"8px\" : pixel(Math.abs(props.adjustedX)),\n        right: props.isFullWidth ? \"8px\" : null,\n    }),\n})`\n    position: absolute;\n    width: fit-content;\n`\n\nconst ArrowContainer = withProps<ArrowContainerProps>(styled.div).attrs({\n    style: (props: ArrowContainerProps) => ({\n        ...(props.shouldOpenDownwards ? openFromBottomStyle : openFromTopStyle),\n        left: pixel(props.x + props.fontPixelWidth / 2),\n        visibility: (props.hideArrow ? \"hidden\" : \"visible\") as VisibilityProperty,\n    }),\n})`\n        position: absolute;\n        width: fit-content;\n`\n\nexport interface ICursorPositionerViewState {\n    isMeasured: boolean\n    isFullWidth: boolean\n    shouldOpenDownward: boolean\n    adjustedX: number\n    adjustedY: number\n    lastMeasuredX: number\n    lastMeasuredY: number\n    lastMeasuredHeight: number\n    lastMeasuredWidth: number\n}\n\n/**\n * Helper component to position an element relative to the current cursor position\n */\nexport class CursorPositionerView extends React.PureComponent<\n    ICursorPositionerViewProps,\n    ICursorPositionerViewState\n> {\n    public state = {\n        isMeasured: false,\n        isFullWidth: false,\n        shouldOpenDownward: false,\n        adjustedX: 0,\n        adjustedY: 0,\n        lastMeasuredX: -1,\n        lastMeasuredY: -1,\n        lastMeasuredHeight: 0,\n        lastMeasuredWidth: 0,\n    }\n\n    private _element: HTMLElement\n    private _resizeObserver: any\n\n    public componentDidMount(): void {\n        if (this._element) {\n            this._measureElement(this._element)\n\n            // tslint:disable-next-line\n            this._resizeObserver = new window[\"ResizeObserver\"]((entries: any) => {\n                if (!entries || !entries.length) {\n                    return\n                }\n\n                const rect: ClientRect = entries[0].contentRect\n\n                if (\n                    rect.width <= this.state.lastMeasuredWidth &&\n                    rect.height <= this.state.lastMeasuredHeight\n                ) {\n                    return\n                }\n\n                this._measureElement(this._element)\n            })\n\n            this._resizeObserver.observe(this._element)\n        }\n    }\n\n    public componentWillUnmount(): void {\n        if (this._resizeObserver) {\n            this._resizeObserver.disconnect()\n            this._resizeObserver = null\n        }\n    }\n\n    public render(): JSX.Element {\n        const adjustedY = this.state.shouldOpenDownward\n            ? this.props.y + this.props.lineHeight * 2.5\n            : this.props.y\n\n        const arrowDirection = this.state.shouldOpenDownward\n            ? ArrowDirection.Up\n            : ArrowDirection.Down\n\n        return (\n            <PositionerContainer\n                isMeasured={this.state.isMeasured}\n                containerWidth={this.props.containerWidth}\n                adjustedY={adjustedY}\n                key={this.props.key}\n            >\n                <PositionerChild\n                    isFullWidth={this.state.isFullWidth}\n                    adjustedX={this.state.adjustedX}\n                    shouldOpenDownwards={this.state.shouldOpenDownward}\n                >\n                    <div ref={elem => (this._element = elem)}>{this.props.children}</div>\n                </PositionerChild>\n                <ArrowContainer\n                    x={this.props.x}\n                    hideArrow={this.props.hideArrow}\n                    fontPixelWidth={this.props.fontPixelWidth}\n                    shouldOpenDownwards={this.state.shouldOpenDownward}\n                >\n                    <Arrow size={10} color={this.props.beakColor} direction={arrowDirection} />\n                </ArrowContainer>\n            </PositionerContainer>\n        )\n    }\n\n    private _measureElement(element: HTMLElement): void {\n        if (element) {\n            const rect = element.getBoundingClientRect()\n\n            if (\n                rect.left === this.state.lastMeasuredX &&\n                rect.top === this.state.lastMeasuredY &&\n                rect.height <= this.state.lastMeasuredHeight &&\n                rect.width <= this.state.lastMeasuredWidth\n            ) {\n                return\n            }\n\n            const margin = this.props.lineHeight * 2\n            const canOpenUpward = this.props.y - rect.height > margin\n            const bottomScreenPadding = 50\n            const canOpenDownwards =\n                this.props.y + rect.height + this.props.lineHeight * 3 <\n                this.props.containerHeight - margin - bottomScreenPadding\n\n            const shouldOpenDownward =\n                (this.props.openDirection !== OpenDirection.Down && !canOpenUpward) ||\n                (this.props.openDirection === OpenDirection.Down && canOpenDownwards)\n\n            const rightBounds = this.props.x + rect.width\n\n            const isFullWidth = rect.width > this.props.containerWidth\n\n            let adjustedX = this.props.x\n\n            if (!isFullWidth && rightBounds > this.props.containerWidth) {\n                const offset = rightBounds - this.props.containerWidth + 8\n                adjustedX = this.props.x - offset\n            }\n\n            this.setState({\n                isFullWidth,\n                shouldOpenDownward,\n                adjustedX,\n                isMeasured: true,\n                lastMeasuredX: rect.left,\n                lastMeasuredY: rect.top,\n                lastMeasuredWidth: rect.width,\n                lastMeasuredHeight: rect.height,\n            })\n        }\n    }\n}\n\nconst mapStateToProps = (\n    state: IState,\n    props?: ICursorPositionerProps,\n): ICursorPositionerViewProps => {\n    const x = props.position ? props.position.pixelX : state.cursorPixelX\n    const y = props.position ? props.position.pixelY : state.cursorPixelY\n\n    const lineHeight = state.fontPixelHeight\n\n    const backgroundColor = state.colors[\"editor.background\"]\n\n    const beakColor = props && props.beakColor ? props.beakColor : backgroundColor\n\n    return {\n        beakColor,\n        fontPixelWidth: state.fontPixelWidth,\n        x: x - state.fontPixelWidth / 2,\n        y: y - state.fontPixelHeight,\n        containerWidth: state.viewport.width,\n        containerHeight: state.viewport.height,\n        lineHeight,\n        backgroundColor,\n    }\n}\n\nexport const CursorPositioner = connect(mapStateToProps)(CursorPositionerView)\n"
  },
  {
    "path": "browser/src/UI/components/Definition.tsx",
    "content": "/**\n * Definition.tsx\n *\n * UX for when the 'go-to definition' gesture is available\n */\n\nimport * as React from \"react\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport * as Oni from \"oni-api\"\n\nconst DefinitionAppearKeyFrames = keyframes`\n    from {opacity: 0; transform: translateY(2px);}\n    to {opacity: 0.4; transform: translateY(0px);}\n`\n\nconst StyledDefinition = styled.div`\n    animation-name: ${DefinitionAppearKeyFrames};\n    animation-duration: 0.25s;\n    animation-delay: 0.25s;\n    animation-fill-mode: forwards;\n    animation-timing-function: ease-in;\n    opacity: 0;\n`\n\nexport interface IDefinitionProps {\n    range: types.Range\n    fontWidthInPixels: number\n    fontHeightInPixels: number\n\n    color: string\n\n    bufferToScreen: Oni.Coordinates.BufferToScreen\n    screenToPixel: Oni.Coordinates.ScreenToPixel\n}\n\nexport class Definition extends React.PureComponent<IDefinitionProps, {}> {\n    public render(): JSX.Element {\n        if (!this.props.range || !this.props.bufferToScreen) {\n            return null\n        }\n\n        const startScreenPosition = this.props.bufferToScreen(this.props.range.start)\n        const endScreenPosition = this.props.bufferToScreen(this.props.range.end)\n\n        if (!startScreenPosition || !endScreenPosition) {\n            return null\n        }\n\n        // TODO: If a range spans multiple lines, break up into multiple screen ranges\n        if (startScreenPosition.screenY !== endScreenPosition.screenY) {\n            return null\n        }\n\n        const startPixelPosition = this.props.screenToPixel(startScreenPosition)\n        const endPixelPosition = this.props.screenToPixel(endScreenPosition)\n\n        const style: React.CSSProperties = {\n            position: \"absolute\",\n            top: startPixelPosition.pixelY + \"px\",\n            left: startPixelPosition.pixelX + \"px\",\n            height: this.props.fontHeightInPixels + \"px\",\n            width:\n                endPixelPosition.pixelX -\n                startPixelPosition.pixelX +\n                this.props.fontWidthInPixels +\n                \"px\",\n            borderBottom: \"1px solid \" + this.props.color,\n        }\n\n        return <StyledDefinition style={style} />\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/Error.tsx",
    "content": "/**\n * Error.tsx\n *\n * Various UI components related to showing errors on screen\n */\n\nimport * as React from \"react\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { getColorFromSeverity } from \"./../../Services/Diagnostics\"\n\nimport { Icon } from \"./../Icon\"\nimport { bufferScrollBarSize, pixel, styled, withProps } from \"./common\"\n\nexport interface IErrorsProps {\n    errors: types.Diagnostic[]\n    fontWidthInPixels: number\n    fontHeightInPixels: number\n\n    bufferToScreen: Oni.Coordinates.BufferToScreen\n    screenToPixel: Oni.Coordinates.ScreenToPixel\n}\n\nconst padding = 8\n\nexport const Errors = (props: IErrorsProps) => {\n    const errors = props.errors || []\n\n    if (!props.bufferToScreen) {\n        return null\n    }\n\n    const markers = errors.map((error, idx) => {\n        const screenSpaceStart = props.bufferToScreen(\n            types.Position.create(error.range.start.line, error.range.start.character),\n        )\n        if (!screenSpaceStart) {\n            return null\n        }\n\n        const screenLine = screenSpaceStart.screenY\n\n        const screenY = screenLine\n        const pixelPosition = props.screenToPixel({ screenX: 0, screenY })\n        const pixelY = pixelPosition.pixelY - padding / 2\n\n        return (\n            <ErrorMarker\n                y={pixelY}\n                text={error.message}\n                color={getColorFromSeverity(error.severity)}\n                key={`${error.code}-${error.message}-${error.severity}-${idx}`}\n            />\n        )\n    })\n\n    const squiggles = errors\n        .filter(e => e && e.range && e.range.start && e.range.end)\n        .map((error, idx) => {\n            const lineNumber = error.range.start.line\n            const column = error.range.start.character\n            const endColumn = error.range.end.character\n\n            const startPosition = props.bufferToScreen(types.Position.create(lineNumber, column))\n\n            if (!startPosition) {\n                return null\n            }\n\n            const endPosition = props.bufferToScreen(types.Position.create(lineNumber, endColumn))\n\n            if (!endPosition) {\n                return null\n            }\n\n            const pixelStart = props.screenToPixel(startPosition)\n            const pixelEnd = props.screenToPixel(endPosition)\n            const pixelWidth = pixelEnd.pixelX - pixelStart.pixelX\n            const normalizedPixelWidth = pixelWidth === 0 ? props.fontWidthInPixels : pixelWidth\n\n            return (\n                <ErrorSquiggle\n                    y={pixelStart.pixelY}\n                    height={props.fontHeightInPixels}\n                    x={pixelStart.pixelX}\n                    width={normalizedPixelWidth}\n                    color={getColorFromSeverity(error.severity)}\n                    key={`${error.code}-${error.message}-${error.severity}-${idx}`}\n                />\n            )\n        })\n\n    return (\n        <div>\n            {markers}\n            {squiggles}\n        </div>\n    )\n}\n\ninterface IErrorMarkerProps {\n    y: number\n    text: string\n    color: string\n}\n\nconst ErrorMarker = (props: IErrorMarkerProps) => (\n    <ErrorMarkerWrapper topOffset={props.y}>\n        <ErrorIcon color={props.color} />\n    </ErrorMarkerWrapper>\n)\n\ninterface ErrorMarkerProps {\n    topOffset: number\n}\n\nconst ErrorMarkerWrapper = withProps<ErrorMarkerProps>(styled.div).attrs({\n    style: (props: ErrorMarkerProps) => ({\n        top: pixel(props.topOffset),\n    }),\n})`\n    position: absolute;\n    right: ${bufferScrollBarSize};\n    opacity: 0.5;\n    background-color: rgb(80, 80, 80);\n    padding: 4.5px 7px;\n`\n\ninterface IErrorIconProps {\n    color: string\n}\n\nexport const ErrorIcon = (props: IErrorIconProps) => (\n    <IconContainer color={props.color}>\n        <Icon name=\"exclamation-circle\" />\n    </IconContainer>\n)\n\nconst IconContainer = withProps<{ color: string }>(styled.div)`\n    color: ${props => props.color};\n`\n\ninterface IErrorSquiggleProps {\n    x: number\n    y: number\n    height: number\n    width: number\n    color: string\n}\n\nconst ErrorSquiggle = withProps<IErrorSquiggleProps>(styled.div).attrs({\n    style: (props: IErrorSquiggleProps) => ({\n        top: pixel(props.y),\n        left: pixel(props.x),\n        height: pixel(props.height),\n        width: pixel(props.width),\n        borderBottom: `1px dashed ${props.color}`,\n    }),\n})`\n    position: absolute;\n`\n"
  },
  {
    "path": "browser/src/UI/components/ErrorInfo.tsx",
    "content": "import * as React from \"react\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport styled from \"./common\"\nimport { ErrorIcon } from \"./Error\"\n\nimport { getColorFromSeverity } from \"./../../Services/Diagnostics\"\n\nexport interface IErrorInfoProps {\n    hasQuickInfo: boolean\n    errors: types.Diagnostic[]\n}\n\nexport const DiagnosticMessage = styled.span`\n    margin-left: 1em;\n`\n\ntype StyleProps = Pick<IErrorInfoProps, \"hasQuickInfo\">\n\nconst DiagnosticContainer = styled<StyleProps, \"div\">(\"div\")`\n    user-select: none;\n    cursor: default;\n    border-bottom: ${p => (p.hasQuickInfo ? `1px solid ${p.theme[\"toolTip.border\"]}` : \"\")};\n`\n\nexport const Diagnostic = styled.div`\n    margin: 8px;\n    display: flex;\n    flex-direction: row;\n`\n\n/**\n * Helper component to render errors in the QuickInfo bubble\n */\nexport const ErrorInfo = (props: IErrorInfoProps) => {\n    return (\n        props.errors && (\n            <DiagnosticContainer hasQuickInfo={props.hasQuickInfo}>\n                {props.errors.map((e, idx) => (\n                    <Diagnostic key={e.code + e.message + e.source + idx}>\n                        <ErrorIcon color={getColorFromSeverity(e.severity)} />\n                        <DiagnosticMessage data-id=\"diagnostic-message\">\n                            {e.message}\n                        </DiagnosticMessage>\n                    </Diagnostic>\n                ))}\n            </DiagnosticContainer>\n        )\n    )\n}\n"
  },
  {
    "path": "browser/src/UI/components/ExternalMenus.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport styled from \"styled-components\"\n\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\nimport { withProps } from \"./common\"\n\ninterface IMenuProps {\n    loaded: boolean\n    visible: boolean\n}\n\nconst MenuContainer = withProps<IMenuProps>(styled.div)`\n    ${p => !p.visible && `visibility: hidden`};\n    position: absolute;\n    box-sizing: border-box;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    padding: 8px;\n    top: 0px;\n    left: 0px;\n    bottom: 0px;\n    right: 0px;\n    ${p => p.loaded && `background-color: rgba(0, 0, 0, 0.25)`};\n    transition: background-color 0.2s ease-in;\n`\n\ninterface Props {\n    commandLine: State.ICommandLine\n    wildmenu: State.IWildMenu\n}\n\nexport class ExternalMenus extends React.Component<Props> {\n    public render() {\n        const { wildmenu, commandLine } = this.props\n        const visible = commandLine.visible || wildmenu.visible\n        return (\n            <MenuContainer visible={visible} loaded={commandLine.visible && wildmenu.visible}>\n                {this.props.children}\n            </MenuContainer>\n        )\n    }\n}\n\nconst mapStateToProps = ({ wildmenu, commandLine }: State.IState) => ({\n    commandLine,\n    wildmenu,\n})\n\nexport default connect(mapStateToProps)(ExternalMenus)\n"
  },
  {
    "path": "browser/src/UI/components/FlipCard.tsx",
    "content": "/**\n * FlipCard.tsx\n *\n * Component that flips between a 'front' and a 'back'\n */\n\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\n\nexport interface IFlipCardProps {\n    front: JSX.Element\n    back: JSX.Element\n\n    isFlipped: boolean\n}\n\nconst FlipCardWrapper = styled.div`\n    position: relative;\n    transform-style: preserve-3d;\n    width: 100%;\n    height: 100%;\n\n    & .front,\n    & .back {\n        margin: 0;\n        display: block;\n        position: absolute;\n        width: 100%;\n        height: 100%;\n        backface-visibility: hidden;\n    }\n\n    & .back {\n        transform: rotateY(180deg);\n    }\n\n    transition-duration: 1s;\n    transition-property: transform;\n`\n\nexport const FlipCard = (props: IFlipCardProps): JSX.Element => {\n    const style: React.CSSProperties = {\n        transform: props.isFlipped ? \"rotateY(180deg)\" : \"rotateY(0deg)\",\n    }\n\n    return (\n        <FlipCardWrapper style={style}>\n            <div className=\"front\">{props.front}</div>\n            <div className=\"back\">{props.back}</div>\n        </FlipCardWrapper>\n    )\n}\n"
  },
  {
    "path": "browser/src/UI/components/HighlightText.tsx",
    "content": "import * as React from \"react\"\n\ninterface IHighlightTextProps {\n    highlightComponent: React.ReactType\n    highlightText: string\n    text: string\n    className?: string\n}\n\nexport const HighlightText = ({\n    highlightComponent: HighlightComponent,\n    highlightText,\n    text = \"\",\n    className,\n}: IHighlightTextProps) => {\n    const letterCountDictionary = createLetterCountDictionary(highlightText)\n\n    const textCharacters = typeof text === \"string\" ? [...text] : []\n    const childNodes = textCharacters.map((character, index) => {\n        const remainingLetterCountBefore = letterCountDictionary[character]\n        letterCountDictionary[character] = remainingLetterCountBefore - 1\n\n        return remainingLetterCountBefore > 0 ? (\n            <HighlightComponent key={`${index}-${character}`}>{character}</HighlightComponent>\n        ) : (\n            <span key={`${index}-${character}`}>{character}</span>\n        )\n    })\n\n    return <span className={className}>{childNodes}</span>\n}\n\ninterface IHighlightTextByIndexProps {\n    highlightComponent: React.ReactType\n    highlightIndices: number[]\n    text: string\n    className?: string\n}\n\nexport const HighlightTextByIndex = ({\n    highlightComponent: HighlightComponent,\n    highlightIndices = [],\n    text = \"\",\n    className,\n}: IHighlightTextByIndexProps) => {\n    const textCharacters = typeof text === \"string\" ? [...text] : []\n    const childNodes = textCharacters.map(\n        (character, index) =>\n            shouldHighlightIndex(index, highlightIndices) ? (\n                <HighlightComponent key={`${index}-${highlightIndices}-${character}`}>\n                    {character}\n                </HighlightComponent>\n            ) : (\n                <span key={`${index}-${highlightIndices}-${character}`}>{character}</span>\n            ),\n    )\n\n    return <span className={className}>{childNodes}</span>\n}\n\nfunction shouldHighlightIndex(index: number, highlights: number[]): boolean {\n    return highlights.indexOf(index) >= 0\n}\n\nexport interface LetterCountDictionary {\n    [letter: string]: number\n}\n\nexport function createLetterCountDictionary(text: string) {\n    const textCharacters = [...text]\n    return textCharacters.reduce(\n        (dictionary, character) => {\n            const currentLetterCount = dictionary[character] || 0\n            dictionary[character] = currentLetterCount + 1\n            return dictionary\n        },\n        {} as LetterCountDictionary,\n    )\n}\n"
  },
  {
    "path": "browser/src/UI/components/InstallHelp.less",
    "content": "@import (reference) \"./common.less\";\n\n.install-help {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n\n    background-color: rgb(40, 44, 52);\n    color: @text-color;\n\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n\n    .title {\n        text-align: center;\n\n        p {\n            font-weight: bold;\n        }\n    }\n\n    .instructions {\n        margin-bottom: 64px;\n\n        li {\n            margin: 8px;\n        }\n    }\n\n    a {\n        color: @text-color-highlight;\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/InstallHelp.tsx",
    "content": "import * as React from \"react\"\n\nimport { connect } from \"react-redux\"\n\nimport { remote } from \"electron\"\n\nimport { Icon, IconSize } from \"./../Icon\"\n\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nexport interface InstallHelpViewProps {\n    visible: boolean\n}\n\nexport class InstallHelpView extends React.PureComponent<InstallHelpViewProps, {}> {\n    public render(): JSX.Element {\n        if (!this.props.visible) {\n            return null\n        }\n\n        const _onClick = (evt: any) => {\n            remote.shell.openExternal(\"https://github.com/neovim/neovim/wiki/Installing-Neovim\")\n            evt.preventDefault()\n        }\n\n        const _onClickIssue = (evt: any) => {\n            remote.shell.openExternal(\"https://github.com/onivim/oni/issues\")\n            evt.preventDefault()\n        }\n\n        return (\n            <div className=\"install-help enable-mouse\">\n                <div className=\"title\">\n                    <Icon name=\"warning\" size={IconSize.FiveX} />\n                    <h1>Uh oh! Unable to launch Neovim...</h1>\n                    <p>Neovim v0.2.1 is required to run Oni.</p>\n                </div>\n                <div className=\"instructions\">\n                    <ul>\n                        <li>\n                            <span>Install neovim from here: </span>\n                            <a href=\"#\" onClick={evt => _onClick(evt)}>\n                                Installing Neovim\n                            </a>\n                        </li>\n                        <li>\n                            Run `nvim --version` from your command prompt to verify you're good to\n                            go!\n                        </li>\n                        <li>Close and re-open Oni</li>\n                    </ul>\n                </div>\n                <div>\n                    If this issue persists, help us by logging an{\" \"}\n                    <a href=\"#\" onClick={evt => _onClickIssue}>\n                        issue!\n                    </a>\n                </div>\n            </div>\n        )\n    }\n}\n\nconst mapStateFromProps = (state: State.IState): InstallHelpViewProps => ({\n    visible: state.neovimError,\n})\n\nexport const InstallHelp = connect(mapStateFromProps)(InstallHelpView)\n"
  },
  {
    "path": "browser/src/UI/components/KeyBindingInfo.tsx",
    "content": "/**\n * KeyBindingInfo.tsx\n *\n * Helper component to show a key binding, based on a command\n */\n\nimport styled from \"styled-components\"\n\nimport * as React from \"react\"\n\nimport { parseChordParts } from \"./../../Input/KeyParser\"\nimport { inputManager } from \"./../../Services/InputManager\"\n\nexport interface IKeyBindingInfoProps {\n    command: string\n}\n\nconst KeyWrapper = styled.span`\n    color: ${props => props.theme[\"highlight.mode.normal.background\"]};\n    font-size: 0.9em;\n`\n\nexport class KeyBindingInfo extends React.PureComponent<IKeyBindingInfoProps, {}> {\n    public render(): JSX.Element {\n        if (!inputManager) {\n            return null\n        }\n\n        const boundKeys = inputManager.getBoundKeys(this.props.command)\n\n        if (!boundKeys || !boundKeys.length) {\n            return null\n        }\n\n        // 1. Get the key(s) in the chord binding\n        // 2. Intersperse with \"+\"\n        // 3. Create KeyWrappers for each segment\n        return (\n            <span>\n                {parseChordParts(boundKeys[0])\n                    .reduce((acc, chordKey) => acc.concat(chordKey, \"+\"), [])\n                    .slice(0, -1)\n                    .map((chordPart, index) => <KeyWrapper key={index}>{chordPart}</KeyWrapper>)}\n            </span>\n        )\n    }\n}\n\nexport const render = (props: IKeyBindingInfoProps) => <KeyBindingInfo {...props} />\n"
  },
  {
    "path": "browser/src/UI/components/LightweightText.tsx",
    "content": "import * as React from \"react\"\n\nimport { focusManager } from \"./../../Services/FocusManager\"\nimport { styled, withProps } from \"./../components/common\"\n\nexport interface ITextInputViewProps {\n    onCancel?: () => void\n    onComplete?: (result: string) => void\n    onChange?: (evt: React.ChangeEvent<HTMLInputElement>) => void\n    styles?: any\n\n    defaultValue?: string\n    InputComponent?: any\n}\n\nexport interface IInputProps extends ITextInputViewProps {\n    inputStyles?: any\n    onKeyDown: (evt: React.KeyboardEvent<HTMLInputElement>) => void\n    onChange: (evt: React.ChangeEvent<HTMLInputElement>) => void\n    onFocus: (evt: React.FocusEvent<HTMLInputElement>) => void\n}\n\nconst Input = withProps<IInputProps>(styled.input)`\n    ${p => p.inputStyles};\n`\n\n// TODO: Is there a better value for this?\nconst WordRegex = /[$_a-zA-Z0-9]/i\n\n/**\n * TextInputView is a lightweight input control, that implements some\n * common functionality (like focus management, key handling)\n */\nexport class TextInputView extends React.PureComponent<ITextInputViewProps, {}> {\n    public static defaultProps = {\n        InputComponent: Input,\n    }\n\n    private _element: HTMLInputElement\n\n    public componentDidMount(): void {\n        if (this._element) {\n            focusManager.pushFocus(this._element)\n        }\n    }\n\n    public render(): JSX.Element {\n        const inputStyle: React.CSSProperties = {\n            outline: \"none\",\n            border: \"0px\",\n            transform: \"translateY(0px)\",\n        }\n\n        const defaultValue = this.props.defaultValue || \"\"\n        const { InputComponent } = this.props\n\n        return (\n            <div className=\"input-container enable-mouse\">\n                <InputComponent\n                    type=\"text\"\n                    inputStyles={this.props.styles}\n                    style={inputStyle}\n                    placeholder={defaultValue}\n                    onKeyDown={this._onKeyDown}\n                    onChange={this._onChange}\n                    onFocus={(evt: React.FocusEvent<HTMLInputElement>) =>\n                        evt.currentTarget.select()\n                    }\n                    innerRef={(elem: HTMLInputElement) => (this._element = elem)}\n                />\n            </div>\n        )\n    }\n\n    public componentWillUnmount(): void {\n        if (this._element) {\n            focusManager.popFocus(this._element)\n            this._element = null\n        }\n    }\n\n    private _onChange = (changeEvent: React.ChangeEvent<HTMLInputElement>): void => {\n        if (this.props.onChange) {\n            this.props.onChange(changeEvent)\n        }\n    }\n\n    private _cancel = (): void => {\n        if (this.props.onCancel) {\n            this.props.onCancel()\n        }\n    }\n\n    private _onKeyDown = (keyboardEvent: React.KeyboardEvent<HTMLInputElement>): void => {\n        if (keyboardEvent.keyCode === 27) {\n            this._cancel()\n            return\n        }\n\n        if (keyboardEvent.keyCode === 13) {\n            if (this.props.onComplete) {\n                this.props.onComplete(this._element.value)\n            }\n            return\n        }\n\n        if (this._element && keyboardEvent.ctrlKey) {\n            switch (keyboardEvent.key) {\n                case \"[\":\n                case \"c\":\n                    this._cancel()\n                    break\n                case \"u\": {\n                    this._element.value = \"\"\n                    break\n                }\n                case \"h\": {\n                    const previousValue = this._element.value\n\n                    if (previousValue.length > 0) {\n                        this._element.value = previousValue.substring(0, previousValue.length - 1)\n                    }\n                    break\n                }\n                case \"w\":\n                    {\n                        const previousValue = this._element.value\n                        let idx = previousValue.length - 1\n\n                        while (idx > 0) {\n                            if (!previousValue[idx].match(WordRegex)) {\n                                break\n                            }\n\n                            idx--\n                        }\n\n                        this._element.value = previousValue.substring(0, idx)\n                    }\n                    break\n                default:\n                    return\n            }\n        }\n    }\n}\n\nexport default TextInputView\n"
  },
  {
    "path": "browser/src/UI/components/Loading.tsx",
    "content": "/**\n * Loading.tsx\n *\n * Component to show loading experience\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport * as State from \"./../Shell/ShellState\"\n\nexport interface ILoadingViewProps {\n    visible: boolean\n    backgroundColor: string\n}\n\nexport class LoadingView extends React.PureComponent<ILoadingViewProps, {}> {\n    public render(): JSX.Element {\n        const style: React.CSSProperties = {\n            position: \"absolute\",\n            top: \"0px\",\n            left: \"0px\",\n            right: \"0px\",\n            bottom: \"0px\",\n            backgroundColor: this.props.backgroundColor,\n            display: this.props.visible ? \"block\" : \"none\",\n            opacity: 1,\n            transition: \"opacity 0.5s ease\",\n        }\n\n        return <div style={style} />\n    }\n}\n\nconst mapStateToProps = (state: State.IState): ILoadingViewProps => {\n    return {\n        visible: !state.isLoaded,\n        backgroundColor: state.colors.background,\n    }\n}\n\nexport const Loading = connect(mapStateToProps)(LoadingView)\n"
  },
  {
    "path": "browser/src/UI/components/LoadingSpinner.tsx",
    "content": "/**\n * NeovimSurface.tsx\n *\n * UI layer for the Neovim editor surface\n */\n\nimport * as React from \"react\"\n\nimport styled, { keyframes } from \"styled-components\"\n\nimport { Icon, IconSize } from \"./../Icon\"\nimport { withProps } from \"./common\"\n\nconst keys = keyframes`\n    0% { transform: rotateZ(0deg); }\n    100% { transform: rotateZ(359deg); }\n`\n\nconst LoadingIconWrapper = withProps<IProps>(styled.div)`\n    opacity: 0.1;\n    ${p => p.iconSize && `font-size: ${p.iconSize}`};\n\n    i {\n        animation: ${keys} 1.5s linear infinite;\n    }\n`\n\ninterface IProps {\n    iconSize?: string\n}\n\nexport const LoadingSpinner: React.SFC<IProps> = props => (\n    <LoadingIconWrapper iconSize={props.iconSize}>\n        <Icon name=\"circle-o-notch\" size={IconSize.FourX} />\n    </LoadingIconWrapper>\n)\n"
  },
  {
    "path": "browser/src/UI/components/Octicon.tsx",
    "content": "import Octicon, { getIconByName, iconsByName } from \"@githubprimer/octicons-react\"\nimport * as React from \"react\"\n\nexport type Icons = keyof iconsByName\n\ninterface IProps {\n    name: Icons\n    props?: {}\n}\n\nexport default function OcticonByName({ name, ...props }: IProps) {\n    return <Octicon {...props} icon={getIconByName(name)} />\n}\n"
  },
  {
    "path": "browser/src/UI/components/PureComponentWithDisposeTracking.tsx",
    "content": "/**\n * PureComponentWithDisposeTracking.tsx\n *\n * Component to assist with bookkeeping disposables and managing their lifecycle\n */\n\nimport * as React from \"react\"\n\nimport { IDisposable } from \"oni-types\"\n\nexport class PureComponentWithDisposeTracking<TProps, TState> extends React.PureComponent<\n    TProps,\n    TState\n> {\n    private _subscriptions: IDisposable[] = []\n\n    public componentDidMount(): void {\n        this._cleanExistingSubscriptions()\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanExistingSubscriptions()\n    }\n\n    protected trackDisposable(disposable: IDisposable): void {\n        this._subscriptions.push(disposable)\n    }\n\n    private _cleanExistingSubscriptions(): void {\n        this._subscriptions.forEach(s => s.dispose())\n        this._subscriptions = []\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/QuickInfo.tsx",
    "content": "import * as os from \"os\"\n\nimport * as React from \"react\"\nimport styled, { boxShadowInset, css, Css, fontSizeSmall, withProps } from \"./common\"\n\nexport const QuickInfoWrapper = styled.div`\n    user-select: none;\n    cursor: default;\n`\n\nexport const QuickInfoElement = styled.div`\n    text-overflow: ellipsis;\n    overflow: hidden;\n`\n\nconst codeBlockStyle = css`\n    color: ${p => p.theme.foreground};\n    padding: 0.4em 0.4em 0.4em 0.4em;\n    margin: 0.4em 0.4em 0.4em 0.4em;\n\n    > code {\n        background-color: inherit;\n    }\n`\n\nconst markedCss = css`\n    .marked {\n        margin: 0;\n        padding-right: 0;\n        padding-left: 0;\n    }\n\n    .marked-paragraph {\n        white-space: pre-wrap;\n    }\n\n    .marked-pre {\n        word-wrap: break-word;\n        white-space: pre-wrap;\n        margin: 0;\n    }\n\n    code {\n        white-space: pre-wrap;\n    }\n`\n\nconst smallScrollbar = css`\n    &::-webkit-scrollbar {\n        height: 4px;\n        width: 4px;\n    }\n`\n\nconst childStyles = css`\n    > * {\n        /* necessary to prevent overflow */\n        margin: 0.2rem;\n        max-width: 45vw;\n\n        ${markedCss};\n\n        a {\n            color: ${p => p.theme[\"highlight.mode.normal.background\"]};\n        }\n    }\n\n    /*\n    All code blocks are set to black but\n    this is overriden for code blocks INSIDE a Pre element\n    */\n\n    code {\n        background-color: ${p => p.theme[\"editor.hover.contents.codeblock.background\"]};\n        color: ${p => p.theme[\"editor.hover.contents.codeblock.foreground\"]};\n        padding: 0 0.2rem;\n    }\n`\n\ninterface DocProps {\n    tokenStyles?: Css\n}\nexport const Documentation = withProps<DocProps>(styled.div)`\n    ${fontSizeSmall};\n    ${boxShadowInset};\n    overflow: hidden;\n    max-height: 25vh;\n    padding: 0.5rem;\n    line-height: 1.5;\n    ${smallScrollbar};\n    background-color: ${p => p.theme[\"editor.hover.contents.background\"]};\n    color: ${p => p.theme[\"editor.hover.contents.foreground\"]};\n    ${markedCss};\n    ${p => p.tokenStyles};\n\n    &:hover {\n        overflow: overlay;\n    }\n\n    ${childStyles};\n\n    pre {\n        ${smallScrollbar};\n        ${codeBlockStyle};\n    }\n`\n\ninterface TitleProps {\n    padding?: string\n    tokenStyles?: Css\n}\n\nexport const Title = withProps<TitleProps>(styled.div)`\n    padding: ${p => p.padding || \"0.7rem\"};\n    overflow: hidden;\n    max-height: 22vh;\n    max-width: 45vw;\n    word-break: break-all;\n    ${smallScrollbar};\n    background-color:${p => p.theme[\"editor.hover.title.background\"]};\n    color: ${p => p.theme[\"editor.hover.title.foreground\"]};\n    white-space: pre-wrap;\n    ${markedCss};\n    ${p => p.tokenStyles};\n\n    &:hover {\n        overflow: overlay;\n    }\n\n    > * {\n        margin: 0.2rem;\n        a {\n            color: ${p => p.theme[\"editor.foreground\"]}\n        }\n    }\n`\n\nexport const QuickInfoContainer = withProps<{ hasDocs: boolean }>(styled.div)`\n  max-height: fit-content;\n  overflow: hidden;\n  width: 100%;\n  padding-bottom: ${p => (p.hasDocs ? \"0.5rem\" : \"0\")};\n  background-color: ${p => p.theme[\"editor.hover.contents.background\"]};\n`\n\nexport interface ITextProps {\n    tokenStyles?: Css\n    padding?: string\n    text?: string\n    html?: {\n        __html: string\n    }\n}\n\nexport class QuickInfoTitle extends React.PureComponent<ITextProps> {\n    public render(): JSX.Element {\n        const { html, text, padding, tokenStyles } = this.props\n        if (!html && !text) {\n            return null\n        }\n\n        return (\n            <Title padding={padding} dangerouslySetInnerHTML={html} tokenStyles={tokenStyles}>\n                {text}\n            </Title>\n        )\n    }\n}\n\nexport class QuickInfoDocumentation extends React.PureComponent<ITextProps> {\n    public render(): JSX.Element {\n        const { text, html, tokenStyles } = this.props\n        switch (true) {\n            case Boolean(text):\n                const lines = this.props.text.split(os.EOL)\n                const divs = lines.map((l, i) => <div key={`${l}-${i}`}>{l}</div>)\n\n                return <Documentation>{divs}</Documentation>\n            case Boolean(html && html.__html.length):\n                return (\n                    <Documentation\n                        dangerouslySetInnerHTML={this.props.html}\n                        tokenStyles={tokenStyles}\n                    />\n                )\n            default:\n                return null\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/QuickInfoContainer.tsx",
    "content": "import * as React from \"react\"\n\nimport { QuickInfoContainer, QuickInfoDocumentation, QuickInfoTitle } from \"./QuickInfo\"\n\nimport TokenThemeProvider from \"./../../Services/SyntaxHighlighting/TokenThemeProvider\"\nimport { getInstance as TokenColorsInstance } from \"./../../Services/TokenColors\"\n\ninterface IQuickInfoProps {\n    titleAndContents: ITitleAndContents\n    isVisible: boolean\n}\n\ninterface ITitleAndContents {\n    title: {\n        __html: string\n    }\n    description: {\n        __html: string\n    }\n}\n\nclass QuickInfoHoverContainer extends React.Component<IQuickInfoProps> {\n    public render() {\n        const { tokenColors } = TokenColorsInstance()\n        const { titleAndContents, isVisible } = this.props\n        const hasTitle = !!(titleAndContents && titleAndContents.title.__html)\n        const hasDocs =\n            hasTitle &&\n            !!(\n                titleAndContents &&\n                titleAndContents.description &&\n                titleAndContents.description.__html\n            )\n\n        return (\n            isVisible && (\n                <TokenThemeProvider\n                    tokenColors={tokenColors}\n                    render={({ styles }) => (\n                        <QuickInfoContainer hasDocs={hasDocs}>\n                            <QuickInfoTitle\n                                tokenStyles={styles}\n                                padding={hasDocs && \"0.5rem\"}\n                                html={titleAndContents.title}\n                            />\n                            {titleAndContents.description && (\n                                <QuickInfoDocumentation\n                                    html={titleAndContents.description}\n                                    tokenStyles={styles}\n                                />\n                            )}\n                        </QuickInfoContainer>\n                    )}\n                />\n            )\n        )\n    }\n}\n\nexport default QuickInfoHoverContainer\n"
  },
  {
    "path": "browser/src/UI/components/RedErrorScreen.tsx",
    "content": "/**\n * Component displaying an error message when there is a failure\n */\n\nimport * as React from \"react\"\nimport styled from \"styled-components\"\n\nexport interface RedErrorScreenViewProps {\n    error: Error\n    info: React.ErrorInfo\n}\n\nconst RedScreenWrapper = styled.div`\n    width: 100%;\n    height: 100%;\n    background-color: rgba(255, 56, 96, 0.5);\n    color: white;\n\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n\n    pointer-events: all;\n`\n\nconst RedScreenContentsWrapper = styled.div`\n    max-width: 800px;\n`\n\nconst HeaderTitleWrapper = styled.div`\n    font-size: 2em;\n    font-weight: bold;\n`\n\nconst HeaderSubtitleWrapper = styled.div`\n    font-size: 1.2em\n    font-weight: bold;\n`\n\nconst ErrorSectionWrapper = styled.div`\n    font-weight: bold;\n    margin-top: 3em;\n    margin-bottom: 1em;\n`\n\nconst ErrorTextWrapper = styled.div`\n    -webkit-user-select: text;\n`\n\nconst ButtonsWrapper = styled.div`\n    display: flex;\n    flex-direction: row;\n\n    margin-top: 4em;\n`\n\nimport { SidebarButton } from \"./SidebarButton\"\n\nimport { remote } from \"electron\"\n\nconst openDebugger = () => remote.getCurrentWebContents().openDevTools()\nconst createIssue = () => remote.shell.openExternal(\"https://github.com/onivim/oni/issues/new\")\n\nexport class RedErrorScreenView extends React.PureComponent<RedErrorScreenViewProps> {\n    public render(): JSX.Element {\n        const errorMessage = this.props.error\n            ? this.props.error.toString()\n            : \"Unable to get error info\"\n\n        const additionalStack =\n            this.props.info && this.props.info.componentStack\n                ? this.props.info.componentStack.toString()\n                : \"None\"\n\n        return (\n            <RedScreenWrapper className=\"red-error-screen\">\n                <RedScreenContentsWrapper>\n                    <HeaderTitleWrapper>Oh no!</HeaderTitleWrapper>\n                    <HeaderSubtitleWrapper>We encountered an error...</HeaderSubtitleWrapper>\n                    <ErrorSectionWrapper>Error:</ErrorSectionWrapper>\n                    <ErrorTextWrapper>{errorMessage}</ErrorTextWrapper>\n                    <ErrorSectionWrapper>Additional Info:</ErrorSectionWrapper>\n                    <ErrorTextWrapper>{additionalStack}</ErrorTextWrapper>\n                </RedScreenContentsWrapper>\n                <ButtonsWrapper>\n                    <SidebarButton focused={false} text=\"Open Debugger\" onClick={openDebugger} />\n                    <SidebarButton focused={false} text=\"Create an Issue\" onClick={createIssue} />\n                </ButtonsWrapper>\n            </RedScreenWrapper>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/SectionTitle.tsx",
    "content": "import * as React from \"react\"\n\nimport Caret from \"./Caret\"\nimport { sidebarItemSelected, styled, withProps } from \"./common\"\n\nexport const Title = styled.h4`\n    margin: 0;\n`\n\nexport const SectionTitle = withProps<Partial<IProps>>(styled.div)`\n    ${sidebarItemSelected};\n    margin: 0.2em 0;\n    padding: 0.2em;\n    background-color: rgba(0, 0, 0, 0.2);\n    display: flex;\n    justify-content: space-between;\n`\n\ninterface IProps {\n    active: boolean\n    isSelected: boolean\n    title: string\n    onClick: () => void\n    count?: number\n    testId: string\n}\n\nconst SidebarSectionTitle: React.SFC<IProps> = props => (\n    <SectionTitle isSelected={props.isSelected} data-test={props.testId} onClick={props.onClick}>\n        <Caret active={props.active} />\n        <Title>{props.title.toUpperCase()}</Title>\n        <strong>{props.count}</strong>\n    </SectionTitle>\n)\n\nexport default SidebarSectionTitle\n"
  },
  {
    "path": "browser/src/UI/components/SidebarButton.tsx",
    "content": "/**\n * SidebarEmptyPaneView.tsx\n */\n\nimport * as React from \"react\"\nimport styled from \"styled-components\"\nimport { boxShadow, withProps } from \"./common\"\n\nconst ButtonWrapper = styled.button`\n    background-color: ${props => props.theme.background};\n    color: ${props => props.theme.foreground};\n    padding: 1em;\n    border: 2px solid transparent;\n    width: 100%;\n    outline: none;\n    cursor: pointer;\n    transition: all 0.1s ease-in;\n\n    pointer-events: all;\n\n    &:hover {\n        ${boxShadow} transform: translateY(-1px);\n    }\n`\n\nexport interface ButtonContainerProps {\n    selected: boolean\n}\n\nconst ButtonContainer = withProps<ButtonContainerProps>(styled.div)`\n    padding-left: 32px;\n    padding-right: 32px;\n\n    transition: all 0.1s ease-in;\n\n    background-color: ${props => (props.selected ? \"rgba(0, 0, 0, 0.1)\" : \"transparent\")};\n    border-left: 2px solid ${props =>\n        props.selected ? props.theme[\"highlight.mode.normal.background\"] : \"transparent\"};\n`\n\nimport { Sneakable } from \"./Sneakable\"\n\nexport interface ISidebarButtonProps {\n    focused: boolean\n    text: string | JSX.Element\n    onClick: () => void\n}\n\nexport class SidebarButton extends React.PureComponent<ISidebarButtonProps, {}> {\n    public render(): JSX.Element {\n        return (\n            <ButtonContainer selected={this.props.focused}>\n                <Sneakable callback={this.props.onClick}>\n                    <ButtonWrapper onClick={this.props.onClick}>\n                        <span>{this.props.text}</span>\n                    </ButtonWrapper>\n                </Sneakable>\n            </ButtonContainer>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/SidebarEmptyPaneView.tsx",
    "content": "/**\n * SidebarEmptyPaneView.tsx\n */\n\nimport * as React from \"react\"\nimport styled from \"styled-components\"\n\nexport interface ISidebarEmptyPaneViewProps {\n    active: boolean\n    contentsText: string\n    actionButtonText?: string\n    onClickButton?: () => void\n}\n\nconst Wrapper = styled.div`\n    border-top: 1px solid ${props => props.theme.background};\n\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n`\n\nimport { SidebarButton } from \"./SidebarButton\"\nimport { VimNavigator } from \"./VimNavigator\"\n\nconst Description = styled.div`\n    margin: 32px;\n    font-size: 0.9em;\n    text-align: center;\n`\n\nexport class SidebarEmptyPaneView extends React.PureComponent<ISidebarEmptyPaneViewProps, {}> {\n    public render(): JSX.Element {\n        const button = this.props.actionButtonText ? (\n            <SidebarButton\n                focused={this.props.active}\n                text={this.props.actionButtonText}\n                onClick={() => this.props.onClickButton && this.props.onClickButton()}\n            />\n        ) : null\n\n        return (\n            <VimNavigator\n                ids={[\"empty.button\"]}\n                active={this.props.active}\n                onSelected={() => this.props.onClickButton && this.props.onClickButton()}\n                render={(selectedId: string) => {\n                    return (\n                        <Wrapper>\n                            <Description>{this.props.contentsText}</Description>\n                            {button}\n                        </Wrapper>\n                    )\n                }}\n            />\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/SidebarItemView.tsx",
    "content": "/**\n * SidebarItemView.tsx\n *\n * Shared component for sidebar items\n */\n\nimport * as React from \"react\"\n\nimport { OniStyledProps, pixel, styled, withProps } from \"./common\"\n\nimport Caret from \"./../../UI/components/Caret\"\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\n\ninterface IItemProps {\n    yanked?: boolean\n    updated?: boolean\n    isOver?: boolean\n    canDrop?: boolean\n    didDrop?: boolean\n    isFocused: boolean\n    isContainer?: boolean\n    icon?: JSX.Element\n    text: string | JSX.Element\n    onClick: (e?: React.MouseEvent<HTMLElement>) => void\n}\n\nexport interface ISidebarItemViewProps extends IItemProps {\n    indentationLevel: number\n}\n\nexport interface ISidebarContainerViewProps extends IItemProps {\n    isExpanded: boolean\n    indentationLevel?: number\n}\n\ntype SidebarStyleProps = OniStyledProps<ISidebarItemViewProps>\n\nconst INDENT_AMOUNT = 12\n\nconst getLeftBorder = (props: SidebarStyleProps) => {\n    switch (true) {\n        case props.isFocused:\n            return `4px solid  ${props.theme[\"highlight.mode.normal.background\"]}`\n        case !props.isContainer:\n            return \"4px solid transparent\"\n        case props.isContainer:\n            return `4px solid rgba(0, 0, 0, 0.2)`\n        default:\n            return \"\"\n    }\n}\n\nconst SidebarItemStyleWrapper = withProps<ISidebarItemViewProps>(styled.div)`\n    padding-left: ${props => pixel(INDENT_AMOUNT * props.indentationLevel)};\n    border-left: ${getLeftBorder};\n    ${p =>\n        (p.isOver || p.yanked) &&\n        `border: 3px solid ${p.theme[\"highlight.mode.insert.background\"]};`};\n    display: flex;\n    flex-direction: row;\n    justify-content: center;\n    align-items: center;\n    padding-top: 4px;\n    padding-bottom: 3px;\n    position: relative;\n    cursor: pointer;\n    pointer-events: all;\n\n    .icon {\n        flex: 0 0 auto;\n        width: 20px;\n        text-align: center;\n        margin-right: 1px;\n    }\n\n    .name {\n        flex: 1 1 auto;\n        overflow: hidden;\n        text-overflow: ellipsis;\n        white-space: nowrap;\n    }\n`\n\nconst getSidebarBackground = (props: SidebarStyleProps) => {\n    if (props.isFocused && !props.isContainer) {\n        return props.theme[\"highlight.mode.normal.background\"]\n    } else if (props.isContainer) {\n        return \"rgb(0, 0, 0)\"\n    } else {\n        return \"transparent\"\n    }\n}\n\nconst SidebarItemBackground = withProps<ISidebarItemViewProps>(styled.div)`\n    background-color: ${getSidebarBackground};\n    opacity: ${props => (props.isContainer || props.isFocused ? \"0.2\" : \"0\")};\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n`\n\nexport const SidebarItemView: React.SFC<ISidebarItemViewProps> = props => {\n    const icon = props.icon ? <div className=\"icon\">{props.icon}</div> : null\n    return (\n        <Sneakable callback={props.onClick}>\n            <SidebarItemStyleWrapper {...props} className=\"item\" onClick={props.onClick}>\n                <SidebarItemBackground {...props} />\n                {icon}\n                <div className=\"name\">{props.text}</div>\n            </SidebarItemStyleWrapper>\n        </Sneakable>\n    )\n}\nconst SidebarContainer = styled.div``\n\nexport const SidebarContainerView: React.SFC<ISidebarContainerViewProps> = ({\n    indentationLevel = 0,\n    ...props\n}) => {\n    return (\n        <SidebarContainer>\n            <SidebarItemView\n                yanked={props.yanked}\n                updated={props.updated}\n                didDrop={props.didDrop}\n                indentationLevel={indentationLevel}\n                icon={<Caret active={props.isExpanded} />}\n                text={props.text}\n                isFocused={props.isFocused}\n                isContainer={props.isContainer}\n                onClick={props.onClick}\n            />\n            {props.isExpanded ? props.children : null}\n        </SidebarContainer>\n    )\n}\n"
  },
  {
    "path": "browser/src/UI/components/Sneakable.tsx",
    "content": "/**\n * Sneakable\n *\n * Helper for easily integrating 'sneak mode' with UI elements\n */\n\nimport * as React from \"react\"\n\nimport { Shapes } from \"oni-api\"\nimport { IDisposable } from \"oni-types\"\n\nimport { /* SneakProvider, Sneak,*/ getInstance as getSneak } from \"./../../Services/Sneak\"\n\nimport { EmptyArray } from \"./../../Utility\"\n\nexport interface ISneakableProps {\n    tag?: string\n    callback?: (evt?: any) => void\n}\n\nexport class Sneakable extends React.PureComponent<ISneakableProps, {}> {\n    private _subscription: IDisposable\n    private _element: HTMLDivElement = null\n\n    public componentDidMount() {\n        this._cleanupSubscription()\n\n        this._subscription = getSneak().addSneakProvider(async () => {\n            if (this._element) {\n                const rect = this._element.getBoundingClientRect()\n\n                return [\n                    {\n                        callback: this.props.callback\n                            ? this.props.callback\n                            : () => this._element.click(),\n                        rectangle: Shapes.Rectangle.create(\n                            rect.left,\n                            rect.top,\n                            rect.width,\n                            rect.height,\n                        ),\n                        tag: this.props.tag || null,\n                    },\n                ]\n            } else {\n                return EmptyArray\n            }\n        })\n    }\n\n    public componentWillUnmount(): void {\n        this._cleanupSubscription()\n    }\n\n    public _cleanupSubscription(): void {\n        if (this._subscription) {\n            this._subscription.dispose()\n            this._subscription = null\n        }\n    }\n\n    public render(): JSX.Element {\n        return <div ref={elem => (this._element = elem)}>{this.props.children}</div>\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/StatusBar.tsx",
    "content": "import styled, { keyframes } from \"styled-components\"\n\nimport * as keys from \"lodash/keys\"\nimport * as React from \"react\"\n\nimport { connect } from \"react-redux\"\n\nimport { addDefaultUnitIfNeeded } from \"./../../Font\"\nimport { withProps } from \"./common\"\nimport StatusResize from \"./StatusResize\"\nimport WithWidth from \"./WithWidth\"\n\nimport { IState, StatusBarAlignment } from \"./../Shell/ShellState\"\n\ninterface StatusBarStyleProps {\n    fontSize: string\n    fontFamily: string\n    className?: string\n}\n\nexport interface StatusBarProps extends StatusBarStyleProps {\n    items: StatusBarItemProps[]\n    enabled: boolean\n}\n\nexport interface StatusBarItemProps {\n    alignment: StatusBarAlignment\n    contents: JSX.Element\n    id: string\n    priority: number\n    count?: number\n    measureRef?: any\n    passWidth?: (data: IChildDimensions) => void\n    width?: number\n    hide?: boolean\n}\n\ninterface IChildDimensions {\n    direction: string\n    width: number\n    id: string\n    priority: number\n    hide: boolean\n}\n\ninterface IStatusComponent {\n    maxWidth?: string\n}\n\nconst enterKeyframes = keyframes`\n    0% { transform: translateY(4px); opacity: 0; }\n    100% { transform: translateY(0px); opacity: 1; }\n`\n\nconst StatusBarComponent = withProps<IStatusComponent>(styled.div)`\n    animation: ${enterKeyframes} 0.2s ease-in;\n    white-space: nowrap;\n    padding-left: 8px;\n    padding-right: 8px;\n    flex: 0 1 auto;\n    height: 100%;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    cursor: pointer;\n\n    &:hover {\n        background-color: rgba(100, 100, 100, 0.2);\n    }`\n\nconst StatusBarContainer = withProps<StatusBarStyleProps>(styled.div)`\n    font-family: ${({ fontFamily }) => fontFamily};\n    font-size: ${({ fontSize }) => fontSize};\n    background-color: ${({ theme }) => theme.background};\n    color: ${({ theme }) => theme.foreground};\n    box-shadow: 0 -8px 20px 0 rgba(0, 0, 0, 0.2);\n    pointer-events: auto;\n    height: 2em;\n    width: 100%;\n    position: relative;\n    user-select: none;\n`\n\n/* `status-bar-inner` is used for performance reasons,\nto move the status bar to its own layer. This keeps changes\nfrom the status-bar layer from cause a repaint in the entire editor */\nconst StatusBarInner = styled.div`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    justify-content: space-between;\n`\n\nexport class StatusBar extends React.PureComponent<StatusBarProps, {}> {\n    public render() {\n        if (!this.props.enabled) {\n            return null\n        }\n\n        const statusBarItems = this.props.items || []\n        const leftItems = statusBarItems\n            .filter(item => item.alignment === StatusBarAlignment.Left)\n            .sort((a, b) => a.priority - b.priority)\n\n        const rightItems = statusBarItems\n            .filter(item => item.alignment === StatusBarAlignment.Right)\n            .sort((a, b) => b.priority - a.priority)\n\n        const statusBarProps = {\n            fontFamily: this.props.fontFamily,\n            fontSize: this.props.fontSize,\n        }\n\n        return (\n            <StatusBarContainer {...statusBarProps}>\n                <StatusBarInner>\n                    <StatusResize direction=\"flex-start\">\n                        {leftItems.map(item => <ItemWithWidth {...item} key={item.id} />)}\n                    </StatusResize>\n                    <StatusResize direction=\"center\" />\n                    <StatusResize direction=\"flex-end\">\n                        {rightItems.map(item => <ItemWithWidth {...item} key={item.id} />)}\n                    </StatusResize>\n                </StatusBarInner>\n            </StatusBarContainer>\n        )\n    }\n}\n\nexport class StatusBarItem extends React.PureComponent<StatusBarItemProps, {}> {\n    public componentDidMount() {\n        this.props.passWidth({\n            width: this.props.width,\n            direction: this.props.alignment === 0 ? \"left\" : \"right\",\n            id: this.props.id,\n            priority: this.props.priority,\n            hide: this.props.hide,\n        })\n    }\n    public componentWillReceiveProps(nextProps: StatusBarItemProps) {\n        if (nextProps.width !== this.props.width) {\n            this.props.passWidth({\n                width: nextProps.width,\n                direction: nextProps.alignment === 0 ? \"left\" : \"right\",\n                id: nextProps.id,\n                priority: nextProps.priority,\n                hide: nextProps.hide,\n            })\n        }\n    }\n\n    public render() {\n        return this.props.hide ? null : (\n            <StatusBarComponent innerRef={this.props.measureRef}>\n                {this.props.contents}\n            </StatusBarComponent>\n        )\n    }\n}\nconst ItemWithWidth = WithWidth(StatusBarItem)\n\nimport { createSelector } from \"reselect\"\n\nconst getStatusBar = (state: IState) => state.statusBar\n\nconst getStatusBarItems = createSelector([getStatusBar], statusBar => {\n    const statusKeys = keys(statusBar)\n\n    const statusBarItems = statusKeys.map(k => ({\n        id: k,\n        ...statusBar[k],\n    }))\n\n    return statusBarItems\n})\n\nconst mapStateToProps = (state: IState): StatusBarProps => {\n    const statusBarItems = getStatusBarItems(state)\n\n    return {\n        fontFamily: state.configuration[\"ui.fontFamily\"],\n        fontSize:\n            state.configuration[\"statusbar.fontSize\"] ||\n            addDefaultUnitIfNeeded(state.configuration[\"ui.fontSize\"]),\n        items: statusBarItems,\n        enabled: state.configuration[\"statusbar.enabled\"],\n    }\n}\n\nexport default connect(mapStateToProps)(StatusBar)\n"
  },
  {
    "path": "browser/src/UI/components/StatusResize.tsx",
    "content": "import * as React from \"react\"\nimport styled from \"styled-components\"\n\nimport { withProps } from \"./common\"\n\ninterface IChildDimensions {\n    direction: string\n    width: number\n    id: string\n    priority: number\n    hide: boolean\n}\n\ntype PassWidth = (data: IChildDimensions) => void\n\ninterface Props {\n    children?: React.ReactNode\n    className?: string\n    passWidth?: PassWidth\n    direction: string\n}\n\ninterface State {\n    containerWidth: number\n    children: {\n        [id: string]: {\n            id: string\n            width: number\n            hide?: boolean\n            priority: number\n        }\n    }\n}\n\ninterface Section {\n    direction: string\n    count: boolean\n}\n\nconst StatusbarSection = withProps<Section>(styled.div)`\n    flex: 1 1 auto;\n    display: ${({ count }) => (count ? `none` : `flex`)};\n    flex-direction: row;\n    height: 100%;\n    max-width: 48%;\n    justify-content: ${props => props.direction};\n`\n\nclass StatusBarResizer extends React.Component<Props, State> {\n    private observer: any\n    private elem: Element\n    constructor(props: Props) {\n        super(props)\n        this.state = {\n            containerWidth: null,\n            children: {},\n        }\n    }\n\n    public componentDidMount() {\n        this.setState({\n            containerWidth: this.elem.getBoundingClientRect().width,\n        })\n        // tslint:disable-next-line\n        this.observer = new window[\"ResizeObserver\"](([entry]: any) => {\n            this.setState({ containerWidth: entry.contentRect.width }, this.resize)\n        })\n        this.observer.observe(this.elem)\n        this.resize()\n    }\n\n    public componentWillUnmount() {\n        this.observer.disconnect()\n    }\n\n    public render() {\n        const { containerWidth } = this.state\n        const { children, direction } = this.props\n        const count = React.Children.count(children)\n        return (\n            <StatusbarSection\n                direction={direction}\n                count={count < 1}\n                innerRef={(elem: Element) => (this.elem = elem)}\n            >\n                {containerWidth !== undefined &&\n                    React.Children.map(children, (child: React.ReactElement<any>) => {\n                        const current = this.state.children[child.props.id]\n                        return React.cloneElement(child, {\n                            ...child.props,\n                            passWidth: this.passWidth,\n                            hide: !!current && current.hide,\n                            containerWidth,\n                        })\n                    })}\n            </StatusbarSection>\n        )\n    }\n\n    private passWidth = (childDimensions: IChildDimensions) => {\n        const { width, id, priority, hide } = childDimensions\n        this.setState(\n            state => ({\n                ...state,\n                children: {\n                    ...state.children,\n                    [id]: { id, width, priority, hide },\n                },\n            }),\n            this.resize,\n        )\n    }\n\n    private resize = () => {\n        const { children, containerWidth } = this.state\n        const childArray = Object.values(children)\n        const sorted = childArray.sort((prev, next) => prev.priority - next.priority)\n\n        // Loop through components sorted by priority check if component can be added without\n        // Overshooting container width if so show the component otherwise hide it\n        const { statusItems } = sorted.reduce(\n            (components, item) => {\n                let hide\n                // add 20 to the trunctation width so components are not too snug\n                if (components.widths + item.width + 20 < containerWidth) {\n                    components.widths += item.width\n                    hide = false\n                } else {\n                    hide = true\n                }\n                components.statusItems[item.id] = {\n                    ...this.state.children[item.id],\n                    hide,\n                }\n                return components\n            },\n            { widths: 0, statusItems: {} },\n        )\n        this.setState({ children: statusItems })\n    }\n}\n\nexport default StatusBarResizer\n"
  },
  {
    "path": "browser/src/UI/components/Tabs.tsx",
    "content": "/**\n * Tabs.tsx\n */\n\nimport * as path from \"path\"\nimport { createSelector } from \"reselect\"\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\n\nimport * as BufferSelectors from \"./../../Editor/NeovimEditor/NeovimEditorSelectors\"\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nimport { addDefaultUnitIfNeeded } from \"./../../Font\"\n\nimport { Sneakable } from \"./../../UI/components/Sneakable\"\nimport { Icon } from \"./../../UI/Icon\"\nimport styled, {\n    boxShadowUp,\n    boxShadowUpInset,\n    css,\n    enableMouse,\n    IThemeColors,\n    keyframes,\n    layer,\n    scrollbarStyles,\n    themeGet,\n} from \"./../components/common\"\n\nimport { FileIcon } from \"./../../Services/FileIcon\"\n\nexport interface ITabProps {\n    id: number\n    name: string\n    description: string\n    isSelected: boolean\n    isDirty: boolean\n    iconFileName?: string\n    userColor?: string\n    shouldWrap?: boolean\n}\n\nexport interface ITabContainerProps {\n    onBufferSelect?: (bufferId: number) => void\n    onBufferClose?: (bufferId: number) => void\n\n    onTabSelect?: (tabId: number) => void\n    onTabClose?: (tabId: number) => void\n}\n\ninterface ITabsWrapperProps {\n    fontFamily: string\n    fontSize: string\n    shouldWrap: boolean\n}\n\nconst TabsWrapper = styled<ITabsWrapperProps, \"div\">(\"div\")`\n    ${enableMouse};\n    ${layer};\n    display: flex;\n    flex-direction: row;\n    ${props => props.shouldWrap && \"flex-wrap: wrap\"};\n    align-items: flex-end;\n    width: 100%;\n    overflow-x: hidden;\n    border-bottom: 4px solid ${themeGet(\"tabs.borderBottom\", \"tabs.background\")};\n    font-family: ${props => props.fontFamily};\n    font-size: ${props => props.fontSize};\n    transform: translateY(-3px);\n    transition: transform 0.25s ease;\n\n    .loaded & {\n        transform: translateY(0px);\n    }\n\n    &:hover {\n        overflow-x: overlay;\n    }\n\n    &::-webkit-scrollbar {\n        height: 3px;\n    }\n    ${scrollbarStyles};\n`\n\nexport interface ITabsProps {\n    onTabSelect?: (id: number) => void\n    onTabClose?: (id: number) => void\n\n    visible: boolean\n    tabs: ITabProps[]\n\n    userColor?: string\n    shouldWrap: boolean\n    maxWidth: string\n    height: string\n    mode: string\n    shouldShowHighlight: boolean\n\n    fontFamily: string\n    fontSize: string\n}\n\nconst InnerName = styled.span`\n    max-width: 20em;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n    overflow: hidden;\n`\n\nexport const Tabs: React.SFC<ITabsProps> = props => {\n    if (!props.visible) {\n        return null\n    }\n\n    const tabs = props.tabs.map(tab => (\n        <Tab\n            {...tab}\n            key={tab.id}\n            onClickName={() => props.onTabSelect(tab.id)}\n            onClickClose={() => props.onTabClose(tab.id)}\n            height={props.height}\n            maxWidth={props.maxWidth}\n            userColor={props.userColor}\n            mode={props.mode}\n            shouldShowHighlight={props.shouldShowHighlight}\n        />\n    ))\n\n    return (\n        <TabsWrapper\n            data-id=\"tabs\"\n            fontFamily={props.fontFamily}\n            fontSize={props.fontSize}\n            shouldWrap={props.shouldWrap}\n        >\n            {tabs}\n        </TabsWrapper>\n    )\n}\n\nexport const Name = styled.div`\n    flex: 1 1 auto;\n    text-align: center;\n    height: 100%;\n\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    margin: 0px 4px;\n`\n\nexport const Corner = styled<{ isHoverEnabled?: boolean }, \"div\">(\"div\")`\n    flex: 0 0 auto;\n    width: 32px;\n    height: 100%;\n\n    display: flex;\n    align-items: center;\n    justify-content: center;\n\n    position: relative;\n\n    ${({ isHoverEnabled }) =>\n        isHoverEnabled &&\n        ` &:hover {\n            background-color: rgba(100, 100, 100, 0.1);\n          }`};\n`\n\nconst DirtyMarker = styled<{ userColor?: string }, \"div\">(\"div\")`\n    width: 8px;\n    height: 8px;\n    border-radius: 4px;\n    background-color: ${props => props.userColor || props.theme.foreground};\n`\n\nconst tabEntranceKeyFrames = keyframes`\n    0% {\n        transform: translateY(-3px) rotateX(-20deg);\n    }\n    100% {\n        transform: translateY(0px) rotateX(0deg);\n    }\n`\n\ninterface ITabWrapperProps {\n    isSelected: boolean\n    isDirty: boolean\n    height: string\n    maxWidth: string\n    mode: string\n    shouldShowHighlight: boolean\n}\n\nconst sanitizedModeForColors = (mode: string): string => {\n    switch (mode) {\n        case \"showmatch\":\n            return \"insert\"\n        case \"cmdline_normal\":\n            return \"normal\"\n        default:\n            return mode\n    }\n}\n\nexport const getHighlightColor = (props: {\n    isSelected: boolean\n    shouldShowHighlight: boolean\n    theme: IThemeColors\n    mode: string\n}) => {\n    if (!props.shouldShowHighlight || !props.isSelected) {\n        return \"transparent\"\n    }\n    const sanitizedMode = sanitizedModeForColors(props.mode)\n    return props.theme[`highlight.mode.${sanitizedMode}.background`]\n}\n\nconst active = css`\n    ${boxShadowUp};\n    opacity: 1;\n`\n\nconst inactive = css`\n    ${boxShadowUpInset};\n    opacity: 0.6;\n\n    &:hover {\n        opacity: 0.9;\n    }\n`\n\nconst TabWrapper = styled<ITabWrapperProps, \"div\">(\"div\")`\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    justify-content: center;\n    cursor: pointer;\n    flex: 0 0 auto;\n    max-width: ${props => props.maxWidth};\n    height: ${props => props.height};\n    transition: opacity 0.25s;\n    overflow: hidden;\n    user-select: none;\n    animation: ${tabEntranceKeyFrames} 0.1s ease-in forwards;\n    ${props => (props.isSelected ? active : inactive)};\n\n    border-top: 2px solid ${getHighlightColor};\n    background-color: ${themeGet(\"tabs.active.background\", \"tabs.background\", \"isSelected\")};\n    color: ${themeGet(\"tabs.active.foreground\", \"tabs.foreground\", \"isSelected\")};\n`\n\nconst tabIconAppearKeyframes = keyframes`\n    0% {\n        transform: scale(0.5);\n    }\n    50% {\n        transform: scale(1.25);\n    }\n    100% {\n        transform: scale(1);\n    }\n`\n\nconst tabIconAppearAnimation = css`\n    animation-name: ${tabIconAppearKeyframes};\n    animation-duration: 0.6s;\n    animation-timing-function: ease-in;\n    animation-fill-mode: forwards;\n    opacity: 1;\n`\n\nconst tabHover = css`\n    ${TabWrapper}:hover & {\n        ${tabIconAppearAnimation};\n    }\n`\n\ninterface IIconContainerProps {\n    isVisibleByDefault: boolean\n    isVisibleOnTabHover?: boolean\n}\n\nconst IconContainer = styled<IIconContainerProps, \"div\">(\"div\")`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    opacity: 0;\n    transition: opacity 0.25s ease-out;\n    ${props => (props.isVisibleByDefault ? tabIconAppearAnimation : \"\")};\n    ${props => props.isVisibleOnTabHover && tabHover};\n`\n\nexport interface ITabPropsWithClick extends ITabProps {\n    onClickName: () => void\n    onClickClose: () => void\n\n    height: string\n    maxWidth: string\n    mode: string\n    shouldShowHighlight: boolean\n}\n\ninterface IScrollIntoView {\n    behavior: string\n    block: string\n    inline: string\n}\n\ninterface IChromeDivElement extends HTMLDivElement {\n    scrollIntoViewIfNeeded: (args: IScrollIntoView) => void\n}\n\nexport class Tab extends React.PureComponent<ITabPropsWithClick> {\n    private _tab = React.createRef<IChromeDivElement>()\n\n    public componentDidUpdate() {\n        this._checkIfShouldScroll()\n    }\n\n    public componentDidMount() {\n        this._checkIfShouldScroll()\n    }\n\n    // reports current state of the tab -> for testing\n    public getStatus(selected: boolean, dirty: boolean) {\n        const selectedState = selected ? \"selected\" : \"not-selected\"\n        const dirtyState = dirty ? \"is-dirty\" : \"not-dirty\"\n        return `tab-${selectedState}-${dirtyState}`\n    }\n\n    public render() {\n        const {\n            name,\n            description,\n            height,\n            maxWidth,\n            mode,\n            isDirty,\n            isSelected,\n            iconFileName,\n            userColor,\n            onClickClose,\n            onClickName,\n            shouldShowHighlight,\n        } = this.props\n\n        const tabStatus = this.getStatus(isSelected, isDirty)\n        return (\n            <Sneakable callback={onClickName} tag={name}>\n                <TabWrapper\n                    mode={mode}\n                    innerRef={this._tab}\n                    data-status={tabStatus}\n                    data-id=\"tab\"\n                    title={description}\n                    height={height}\n                    maxWidth={maxWidth}\n                    isDirty={isDirty}\n                    isSelected={isSelected}\n                    shouldShowHighlight={shouldShowHighlight}\n                >\n                    <Corner data-id=\"tab-icon-corner\" onMouseDown={this.handleTitleClick}>\n                        <FileIcon\n                            fileName={iconFileName}\n                            isLarge={true}\n                            playAppearAnimation={true}\n                        />\n                    </Corner>\n                    <Name onMouseDown={this.handleTitleClick}>\n                        <InnerName>{name}</InnerName>\n                    </Name>\n                    <Corner data-id=\"tab-close-button\" isHoverEnabled onClick={onClickClose}>\n                        <IconContainer isVisibleByDefault={false} isVisibleOnTabHover>\n                            <Icon name=\"times\" />\n                        </IconContainer>\n                        <IconContainer isVisibleByDefault={isDirty}>\n                            <DirtyMarker userColor={userColor} />\n                        </IconContainer>\n                    </Corner>\n                </TabWrapper>\n            </Sneakable>\n        )\n    }\n\n    private _checkIfShouldScroll(): void {\n        if (this.props.isSelected && this._tab) {\n            if (this._tab && this._tab.current && this._tab.current.scrollIntoViewIfNeeded) {\n                this._tab.current.scrollIntoViewIfNeeded({\n                    behavior: \"smooth\",\n                    block: \"center\",\n                    inline: \"center\",\n                })\n            }\n        }\n    }\n\n    private handleTitleClick = (event: React.MouseEvent<HTMLElement>): void => {\n        if (this._isLeftClick(event)) {\n            this.props.onClickName()\n        } else if (this._isMiddleClick(event)) {\n            this.props.onClickClose()\n        }\n    }\n\n    private _isMiddleClick(event: React.MouseEvent<HTMLElement>): boolean {\n        return event.button === 1\n    }\n\n    private _isLeftClick(event: React.MouseEvent<HTMLElement>): boolean {\n        return event.button === 0\n    }\n}\n\nexport const getTabName = (name: string, isDuplicate?: boolean): string => {\n    if (!name) {\n        return \"[No Name]\"\n    }\n\n    const filename = path.basename(name)\n    if (isDuplicate) {\n        const folderAndFile = name\n            .split(path.sep)\n            .slice(-2)\n            .join(path.sep)\n        return folderAndFile\n    }\n\n    return filename\n}\n\nconst getTabState = (state: State.IState) => state.tabState\n\nexport const showTabId = (state: State.IState) => {\n    return state.configuration[\"tabs.showIndex\"]\n}\n\nexport const getIdPrefix = (id: string, shouldShow: boolean): string => {\n    return shouldShow ? id + \": \" : \"\"\n}\n\nexport const shouldShowFileIcon = (state: State.IState): boolean => {\n    return state.configuration[\"tabs.showFileIcon\"]\n}\n\nexport const checkShouldShowHighlight = (state: State.IState): boolean => {\n    return state.configuration[\"tabs.highlight\"] && state.hasFocus\n}\n\nexport const checkTabBuffers = (buffersInTabs: number[], buffers: State.IBuffer[]): boolean => {\n    const tabBufs = buffers.filter(buf => buffersInTabs.find(tabBuf => tabBuf === buf.id))\n\n    return tabBufs.some(buf => buf.modified)\n}\n\nexport const checkDuplicate = (current: string, names: string[]) => {\n    return names.filter((name: string) => path.basename(name) === path.basename(current)).length > 1\n}\n\nconst getTabsFromBuffers = createSelector(\n    [\n        BufferSelectors.getBufferMetadata,\n        BufferSelectors.getActiveBufferId,\n        showTabId,\n        shouldShowFileIcon,\n        checkShouldShowHighlight,\n    ],\n    (\n        allBuffers: State.IBuffer[],\n        activeBufferId: number,\n        shouldShowId: boolean,\n        showFileIcon: boolean,\n        showHighlight: boolean,\n    ) => {\n        const bufferCount = allBuffers.length\n        const names = allBuffers.map(buffer => buffer.file)\n        const tabs = allBuffers.map((buf, idx, buffers) => {\n            const isDuplicate = checkDuplicate(buf.file, names)\n            const isActive =\n                (activeBufferId !== null && buf.id === activeBufferId) || bufferCount === 1\n            const name =\n                getIdPrefix(buf.id.toString(), shouldShowId) + getTabName(buf.file, isDuplicate)\n            return {\n                id: buf.id,\n                name,\n                iconFileName: showFileIcon ? getTabName(buf.file) : \"\",\n                shouldShowHighlight: showHighlight,\n                isSelected: isActive,\n                isDirty: buf.modified,\n                description: buf.file,\n            }\n        })\n        return tabs.sort(({ id: prevId }: ITabProps, { id: nextId }: ITabProps) => prevId - nextId)\n    },\n)\n\nconst getTabsFromVimTabs = createSelector(\n    [getTabState, showTabId, shouldShowFileIcon, BufferSelectors.getBufferMetadata],\n    (\n        tabState: State.ITabState,\n        shouldShowId: boolean,\n        showFileIcon: boolean,\n        allBuffers: State.IBuffer[],\n    ) => {\n        return tabState.tabs.map((t, idx) => ({\n            id: idx + 1,\n            name: getIdPrefix((idx + 1).toString(), shouldShowId) + getTabName(t.name),\n            iconFileName: showFileIcon ? getTabName(t.name) : \"\",\n            isSelected: t.id === tabState.selectedTabId,\n            isDirty: checkTabBuffers(t.buffersInTab, allBuffers),\n            description: t.name,\n        }))\n    },\n)\n\nconst mapStateToProps = (state: State.IState, ownProps: ITabContainerProps): ITabsProps => {\n    const oniTabMode = state.configuration[\"tabs.mode\"]\n    const shouldUseVimTabs = oniTabMode === \"tabs\"\n\n    const tabs = shouldUseVimTabs ? getTabsFromVimTabs(state) : getTabsFromBuffers(state)\n\n    const visible = oniTabMode !== \"native\" && oniTabMode !== \"hidden\"\n\n    const { mode } = state\n    const height = state.configuration[\"tabs.height\"]\n    const maxWidth = state.configuration[\"tabs.maxWidth\"]\n    const shouldWrap = state.configuration[\"tabs.wrap\"]\n    const userColor = state.configuration[\"tabs.dirtyMarker.userColor\"]\n    const shouldShowHighlight = checkShouldShowHighlight(state)\n\n    const selectFunc = shouldUseVimTabs ? ownProps.onTabSelect : ownProps.onBufferSelect\n    const closeFunc = shouldUseVimTabs ? ownProps.onTabClose : ownProps.onBufferClose\n\n    return {\n        fontFamily: state.configuration[\"ui.fontFamily\"],\n        fontSize: addDefaultUnitIfNeeded(state.configuration[\"ui.fontSize\"]),\n        onTabSelect: selectFunc,\n        onTabClose: closeFunc,\n        userColor,\n        height,\n        maxWidth,\n        shouldWrap,\n        mode,\n        shouldShowHighlight,\n        visible,\n        tabs,\n    }\n}\n\nexport const TabsContainer = connect(mapStateToProps)(Tabs)\n"
  },
  {
    "path": "browser/src/UI/components/Text.tsx",
    "content": "import * as React from \"react\"\n\nimport styled from \"./common\"\n\nexport interface ITextProps {\n    text: string\n}\n\nconst Selected = styled.span`\n    font-style: italic;\n    text-decoration: underline;\n`\n\nexport const Text = (props: ITextProps) => <span>{props.text}</span>\n\nexport const SelectedText = (props: ITextProps) => <Selected>{props.text}</Selected>\n"
  },
  {
    "path": "browser/src/UI/components/ToolTip.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport styled from \"styled-components\"\nimport { boxShadow, withProps } from \"./common\"\n\nimport { createSelector } from \"reselect\"\n\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nimport { CursorPositioner } from \"./CursorPositioner\"\n\ninterface IToolTipProps {\n    padding: string\n    fontFamily: string\n}\n\nconst ToolTipContainer = withProps<IToolTipProps>(styled.div)`\n    background-color: ${p => p.theme[\"toolTip.background\"]};\n    color: ${p => p.theme[\"toolTip.foreground\"]};\n    border: ${p => `1px solid ${p.theme[\"editor.hover.border\"]}`};\n    padding: ${p => p.padding};\n    height: auto;\n    font-family: ${p => p.fontFamily};\n    ${boxShadow};\n\n    * {\n        pre {\n            font-family: ${p => p.fontFamily};\n        }\n\n        code {\n            font-family: ${p => p.fontFamily};\n        }\n    }\n`\n\nexport interface IToolTipsViewProps {\n    toolTips: State.IToolTip[]\n    fontFamily: string\n    fontSize: string\n}\n\nexport class ToolTipsView extends React.PureComponent<IToolTipsViewProps, {}> {\n    public render(): JSX.Element {\n        const toolTipElements = this.props.toolTips.map(toolTip => {\n            return <ToolTipView fontFamily={this.props.fontFamily} {...toolTip} key={toolTip.id} />\n        })\n\n        const style: React.CSSProperties = {\n            fontFamily: this.props.fontFamily,\n            fontSize: this.props.fontSize,\n        }\n\n        return (\n            <div className=\"tool-tips\" style={style}>\n                {toolTipElements}\n            </div>\n        )\n    }\n}\n\nexport interface IToolTipViewProps extends State.IToolTip {\n    fontFamily: string\n}\n\nexport class ToolTipView extends React.PureComponent<IToolTipViewProps, {}> {\n    private _container: HTMLElement\n    private _unmount: () => void\n\n    constructor(props: IToolTipViewProps) {\n        super(props)\n    }\n\n    public componentDidMount(): void {\n        const func = (evt: MouseEvent) => this._checkIfClickIsOutside(evt)\n        document.addEventListener(\"mousedown\", func)\n\n        this._unmount = () => document.removeEventListener(\"mousedown\", func)\n    }\n\n    public componentWillUnmount(): void {\n        if (this._unmount) {\n            this._unmount()\n            this._unmount = null\n        }\n    }\n\n    public render(): JSX.Element {\n        const { options, fontFamily } = this.props\n        const { position = null, openDirection = 1, padding = \"8px\" } = options\n\n        return (\n            <CursorPositioner position={position} openDirection={openDirection}>\n                <ToolTipContainer\n                    padding={padding}\n                    fontFamily={fontFamily}\n                    innerRef={(elem: any) => this._setContainer(elem)}\n                >\n                    {this.props.element}\n                </ToolTipContainer>\n            </CursorPositioner>\n        )\n    }\n\n    private _setContainer(element: HTMLElement): void {\n        this._container = element\n    }\n\n    private _checkIfClickIsOutside(evt: MouseEvent): void {\n        if (this._container && !this._container.contains(evt.target as any)) {\n            if (this.props.options.onDismiss) {\n                this.props.options.onDismiss()\n            }\n        }\n    }\n}\n\nconst getToolTips = (state: State.IState) => state.toolTips\n\nconst getToolTipsSelector = createSelector([getToolTips], toolTips => {\n    return Object.keys(toolTips)\n        .map(toolTipId => toolTips[toolTipId])\n        .filter(toolTipState => toolTipState !== null)\n})\n\nconst mapStateToProps = (state: State.IState): IToolTipsViewProps => {\n    const toolTips = getToolTipsSelector(state)\n\n    return {\n        fontFamily: state.fontFamily,\n        fontSize: state.fontSize,\n        toolTips,\n    }\n}\n\nexport const ToolTips = connect(mapStateToProps)(ToolTipsView)\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/Branch.tsx",
    "content": "import * as React from \"react\"\n\nimport { Diff } from \"./../../../Services/VersionControl\"\nimport styled from \"./../../../UI/components/common\"\nimport Octicon, { Icons } from \"./../../../UI/components/Octicon\"\n\ntype ChangeTypes = \"change\" | \"addition\" | \"deletion\"\n\ninterface ICreateIconArgs {\n    type: ChangeTypes\n    num: number\n}\n\nconst BranchContainer = styled.div`\n    height: 100%;\n    width: 100%;\n    display: flex;\n    align-items: center;\n`\n\nconst BranchText = styled.span`\n    min-width: 10px;\n    text-align: center;\n    padding: 2px 4px 0 0;\n    display: flex;\n    align-items: center;\n`\n\nexport const BranchNameContainer = styled.span`\n    width: 100%;\n    margin-left: 4px;\n`\n\nconst ChangeSpanContainer = styled.span`\n    font-size: 0.7rem;\n    padding: 0 0.15rem;\n`\n\nconst ChangeSpan = styled.span`\n    padding-left: 0.25rem;\n`\n\ninterface BranchProps {\n    branch: string\n    children?: React.ReactNode\n    diff: Diff\n}\n\nexport const Branch: React.SFC<BranchProps> = ({ diff, branch, children }) =>\n    branch && (\n        <BranchContainer>\n            <BranchText>\n                <Octicon name=\"git-branch\" />\n                <BranchNameContainer>\n                    {`${branch} `}\n                    {diff && (\n                        <DeletionsAndInsertions\n                            deletions={diff.deletions}\n                            insertions={diff.insertions}\n                        />\n                    )}\n                    {children}\n                </BranchNameContainer>\n            </BranchText>\n        </BranchContainer>\n    )\n\nconst getClassNameForType = (type: ChangeTypes): Icons => {\n    switch (type) {\n        case \"addition\":\n            return \"diff-added\"\n        case \"deletion\":\n            return \"diff-removed\"\n        case \"change\":\n            return \"diff-modified\"\n        default:\n            return \"diff-ignored\"\n    }\n}\n\ninterface ChangesProps {\n    deletions: number\n    insertions: number\n}\n\nexport const DeletionsAndInsertions: React.SFC<ChangesProps> = ({ deletions, insertions }) => (\n    <span>\n        <VCSIcon type=\"addition\" num={insertions} />\n        {!!(deletions && insertions) && <span key={2}>, </span>}\n        <VCSIcon type=\"deletion\" num={deletions} />\n    </span>\n)\n\nexport const VCSIcon: React.SFC<ICreateIconArgs> = ({ type, num }) =>\n    !!num && (\n        <span>\n            <ChangeSpanContainer>\n                <Octicon name={getClassNameForType(type)} />\n            </ChangeSpanContainer>\n            <ChangeSpan data-test={`${type}-${num}`}>{num}</ChangeSpan>\n        </span>\n    )\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/CommitMessage.tsx",
    "content": "import * as React from \"react\"\n\nimport styled from \"./../../components/common\"\nimport TextInput from \"./../LightweightText\"\n\nexport const Explainer = styled.span`\n    width: 100%;\n    padding-left: 0.5rem;\n    text-align: left;\n    font-size: 0.8em;\n    display: block;\n    opacity: 0.4;\n`\n\nconst TextArea = styled.textarea`\n    width: 100%;\n    background-color: inherit;\n    color: inherit;\n    font-size: inherit;\n    font-family: inherit;\n    padding: 0.5em;\n    box-sizing: border-box;\n    overflow: hidden;\n    resize: vertical;\n`\nexport interface ICommitHandlers {\n    handleCommitMessage: (evt: React.ChangeEvent<HTMLInputElement>) => void\n    handleCommitCancel: () => void\n    handleCommitComplete: () => void\n}\n\nconst CommitMessage: React.SFC<ICommitHandlers> = props => (\n    <>\n        <Explainer>Hit enter to commit the file</Explainer>\n        <TextInput\n            InputComponent={TextArea}\n            onChange={props.handleCommitMessage}\n            onCancel={props.handleCommitCancel}\n            onComplete={props.handleCommitComplete}\n            defaultValue=\"Enter a commit message\"\n        />\n    </>\n)\nexport default CommitMessage\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/Commits.tsx",
    "content": "import * as React from \"react\"\n\nimport { Logs } from \"../../../Services/VersionControl/VersionControlProvider\"\nimport styled, { getSelectedBorder } from \"./../../../UI/components/common\"\nimport Octicon from \"./../../../UI/components/Octicon\"\nimport { formatDate } from \"./../../../Utility\"\nimport VCSSectionTitle from \"./../SectionTitle\"\n\ninterface ICommitsSection {\n    commits: Logs[\"all\"]\n    selectedId: string\n    titleId: string\n    visibility: boolean\n    toggleVisibility: () => void\n    onClick: (c: string) => void\n}\n\nconst List = styled.ul`\n    list-style: none;\n    margin: 0;\n    padding: 0;\n    overflow-y: auto;\n    overflow-x: hidden;\n    max-height: 30em;\n`\nexport const ListItem = styled<{ isSelected?: boolean }, \"li\">(\"li\")`\n    border: ${getSelectedBorder};\n    padding: 0.4rem;\n`\n\nconst Detail = styled.p`\n    margin: 0.4rem 0;\n`\n\nconst Container = styled.div`\n    width: 100%;\n    max-height: 20em;\n    overflow: hidden;\n`\n\nconst CommitsSection: React.SFC<ICommitsSection> = ({ commits, ...props }) => {\n    return (\n        <Container>\n            <VCSSectionTitle\n                isSelected={props.selectedId === props.titleId}\n                testId={`${props.titleId}-${commits.length}`}\n                onClick={props.toggleVisibility}\n                active={!!(props.visibility && commits.length)}\n                title=\"Recent Commits\"\n                count={commits.length}\n            />\n            {props.visibility && commits.length ? (\n                <List>\n                    {commits.map(prevCommit => (\n                        <ListItem\n                            key={prevCommit.hash}\n                            onClick={() => props.onClick(prevCommit.hash)}\n                            isSelected={props.selectedId === prevCommit.hash}\n                        >\n                            <Detail>\n                                <Octicon name=\"git-commit\" />\n                                <strong> {prevCommit.message}</strong>\n                            </Detail>\n                            <Detail>{prevCommit.hash.slice(0, 6)}</Detail>\n                            <Detail>{formatDate(prevCommit.date)}</Detail>\n                            <Detail>{prevCommit.author_email}</Detail>\n                            <Detail>{prevCommit.author_name}</Detail>\n                        </ListItem>\n                    ))}\n                </List>\n            ) : null}\n        </Container>\n    )\n}\n\nexport default CommitsSection\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/File.tsx",
    "content": "import * as path from \"path\"\nimport * as React from \"react\"\n\nimport styled, { getSelectedBorder } from \"./../common\"\nimport Octicon, { Icons } from \"./../Octicon\"\nimport { Sneakable } from \"./../Sneakable\"\n\ninterface IProps {\n    onClick: (path: string) => void\n    file: string\n    icon: Icons\n    isSelected: boolean\n}\n\nconst Row = styled.div`\n    border: ${getSelectedBorder};\n    display: flex;\n    padding: 0.3em;\n`\n\nconst truncate = (str: string) =>\n    str\n        .split(path.sep)\n        .slice(-2)\n        .join(path.sep)\n\nconst Name = styled.span`\n    word-wrap: break-word;\n`\n\nconst IconContainer = styled.div`\n    margin-right: 0.5rem;\n`\n\nconst File: React.SFC<IProps> = ({ file, icon, onClick, isSelected }) => (\n    <Sneakable callback={() => onClick(file)} key={file}>\n        <Row onClick={() => onClick(file)} isSelected={isSelected}>\n            <IconContainer>\n                <Octicon name={icon} />\n            </IconContainer>\n            <Name>{truncate(file)}</Name>\n        </Row>\n    </Sneakable>\n)\n\nexport default File\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/Help.tsx",
    "content": "import * as React from \"react\"\n\nimport { inputManager } from \"../../../Services/InputManager\"\nimport styled from \"../common\"\nimport { SectionTitle, Title } from \"./../SectionTitle\"\n\nconst sidebarCommands = [\n    { command: \"vcs.openFile\", description: \"Open the currently selected file\" },\n    { command: \"vcs.unstage\", description: \"Unstage the currently selected file\" },\n    { command: \"vcs.commitAll\", description: \"Commit all staged files\" },\n    { command: \"vcs.refresh\", description: \"Manually refresh vcs pane\" },\n    { command: \"vcs.sidebar.toggle\", description: \"Toggle vcs pane\" },\n]\nconst getBoundKeys = (commands = sidebarCommands) => {\n    return commands.map(({ command, ...rest }) => ({\n        key: inputManager.getBoundKeys(command)[0] || \"Unbound\",\n        ...rest,\n    }))\n}\n\nconst HelpContainer = styled.div``\n\nconst CommandExplainer = styled.div`\n    padding: 0 0.5em;\n`\n\nexport const Description = styled.p`\n    margin: 0.5em 0;\n`\n\nconst Command = styled.span`\n    color: ${p => p.theme[\"highlight.mode.insert.foreground\"]};\n    background-color: ${p => p.theme[\"highlight.mode.insert.background\"]};\n`\n\nconst wrapInBrackets = (str: string) => {\n    return str.startsWith(\"<\") && str.endsWith(\">\") ? str : `<${str}>`\n}\n\nconst Help: React.SFC<{}> = props => {\n    const commands = getBoundKeys()\n    return (\n        <HelpContainer>\n            <SectionTitle>\n                <Title>Help</Title>?\n            </SectionTitle>\n            {commands.map(command => (\n                <CommandExplainer key={command.key}>\n                    <Description>\n                        {command.description} - <Command>{wrapInBrackets(command.key)}</Command>\n                    </Description>\n                </CommandExplainer>\n            ))}\n        </HelpContainer>\n    )\n}\n\nexport default Help\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/Staged.tsx",
    "content": "import * as React from \"react\"\n\nimport styled, { Center, getSelectedBorder, withProps } from \"../common\"\nimport SectionTitle from \"../SectionTitle\"\nimport { LoadingSpinner } from \"./../../../UI/components/LoadingSpinner\"\nimport { Icons } from \"./../../../UI/components/Octicon\"\nimport CommitMessage from \"./CommitMessage\"\nimport File from \"./File\"\n\nconst Explainer = styled.div`\n    width: 100%;\n    text-align: left;\n    display: block;\n    opacity: 0.4;\n    padding: 0.5rem;\n`\n\ninterface IProps {\n    files?: string[]\n    titleId: string\n    selectedId: string\n    icon: Icons\n    loading: boolean\n    handleSelection: (id: string) => void\n    filesToCommit: string[]\n    toggleVisibility: () => void\n    handleCommitMessage: (evt: React.ChangeEvent<HTMLInputElement>) => void\n    handleCommitOne: () => void\n    handleCommitCancel: () => void\n    handleCommitAll: () => void\n    selectedToCommit?: (id: string) => boolean\n    visible: boolean\n}\n\nconst OptionsBar = withProps<{ isSelected: boolean }>(styled.span)`\n    border: ${getSelectedBorder};\n    display: block;\n    width: 100%;\n`\n\nexport const LoadingHandler: React.SFC<{ loading: boolean }> = ({ loading, children }) => (\n    <>\n        {loading ? (\n            <Center>\n                <LoadingSpinner iconSize=\"0.4em\" />\n            </Center>\n        ) : (\n            children\n        )}\n    </>\n)\n\nconst StagedSection: React.SFC<IProps> = props => {\n    const commitAllSelected = \"commit_all\" === props.selectedId\n    return (\n        <div>\n            <SectionTitle\n                isSelected={props.selectedId === props.titleId}\n                testId={`${props.titleId}-${props.files.length}`}\n                onClick={props.toggleVisibility}\n                active={props.visible && !!props.files.length}\n                title={props.titleId}\n                count={props.files.length}\n            />\n            {props.visible && props.files.length ? (\n                <LoadingHandler loading={props.loading && commitAllSelected}>\n                    <OptionsBar isSelected={commitAllSelected}>\n                        {props.selectedToCommit(\"commit_all\") ? (\n                            <CommitMessage\n                                handleCommitCancel={props.handleCommitCancel}\n                                handleCommitComplete={props.handleCommitAll}\n                                handleCommitMessage={props.handleCommitMessage}\n                            />\n                        ) : (\n                            <Explainer onClick={() => props.handleSelection(props.titleId)}>\n                                commit all ({props.files.length})\n                            </Explainer>\n                        )}\n                    </OptionsBar>\n                </LoadingHandler>\n            ) : null}\n            {props.visible &&\n                props.files.map(file => {\n                    const isSelected = file === props.selectedId\n                    const isLoading = props.filesToCommit.includes(file) && props.loading\n                    return (\n                        <LoadingHandler loading={isLoading} key={file}>\n                            {props.selectedToCommit(file) ? (\n                                <CommitMessage\n                                    handleCommitCancel={props.handleCommitCancel}\n                                    handleCommitComplete={props.handleCommitOne}\n                                    handleCommitMessage={props.handleCommitMessage}\n                                />\n                            ) : (\n                                <File\n                                    file={file}\n                                    icon={props.icon}\n                                    onClick={props.handleSelection}\n                                    isSelected={isSelected}\n                                />\n                            )}\n                        </LoadingHandler>\n                    )\n                })}\n        </div>\n    )\n}\n\nexport default StagedSection\n"
  },
  {
    "path": "browser/src/UI/components/VersionControl/Status.tsx",
    "content": "import * as React from \"react\"\n\nimport { Icons } from \"./../Octicon\"\nimport VCSSectionTitle from \"./../SectionTitle\"\nimport File from \"./File\"\n\ninterface IModifiedFilesProps {\n    files?: string[]\n    titleId: string\n    selectedId: string\n    icon: Icons\n    onClick: (id: string) => void\n    toggleVisibility: () => void\n    visibility: boolean\n}\n\nexport const VersionControlStatus: React.SFC<IModifiedFilesProps> = ({\n    files,\n    selectedId,\n    children,\n    icon,\n    onClick,\n    toggleVisibility,\n    titleId,\n    visibility,\n}) => {\n    return (\n        files && (\n            <div>\n                <VCSSectionTitle\n                    isSelected={selectedId === titleId}\n                    testId={`${titleId}-${files.length}`}\n                    onClick={toggleVisibility}\n                    active={visibility && !!files.length}\n                    title={titleId}\n                    count={files.length}\n                />\n                {visibility &&\n                    files.map(file => (\n                        <File\n                            icon={icon}\n                            key={file}\n                            file={file}\n                            onClick={onClick}\n                            isSelected={selectedId === file}\n                        />\n                    ))}\n            </div>\n        )\n    )\n}\n\nexport default VersionControlStatus\n"
  },
  {
    "path": "browser/src/UI/components/VimNavigator.tsx",
    "content": "/*\n * VimNavigator.tsx\n *\n * Component that enables vim-style navigation for React components.\n * You give it a set of ids (or later, a grid), and it will let you\n * know what is selected.\n *\n * Some future plans:\n * - Support a grid\n * - Support multiselection\n */\n\nimport * as React from \"react\"\n\nimport * as Log from \"oni-core-logging\"\nimport { Event } from \"oni-types\"\n\nimport { KeyboardInputView } from \"./../../Input/KeyboardInput\"\nimport { getInstance, IMenuBinding } from \"./../../neovim/SharedNeovimInstance\"\n\nimport styled from \"./../../UI/components/common\"\n\nimport { CallbackCommand, commandManager } from \"./../../Services/CommandManager\"\n\nexport interface IVimNavigatorProps {\n    // activateOnMount: boolean\n    ids: string[]\n\n    active: boolean\n\n    // onEnter: IEvent<void>\n    // onLeave: IEvent<void>\n\n    onSelectionChanged?: (selectedId: string) => void\n    onSelected?: (selectedId: string) => void\n\n    render: (selectedId: string, updateSelection: (id: string) => void) => JSX.Element\n\n    style?: React.CSSProperties\n    idToSelect?: string\n}\n\nexport interface IVimNavigatorState {\n    selectedId: string\n}\n\nconst NavigatorContainer = styled.div`\n    height: 100%;\n`\n\nexport class VimNavigator extends React.PureComponent<IVimNavigatorProps, IVimNavigatorState> {\n    private _activeBinding: IMenuBinding = null\n    private _activateEvent = new Event<void>()\n\n    constructor(props: IVimNavigatorProps) {\n        super(props)\n\n        this.state = {\n            selectedId: props.ids && props.ids.length > 0 ? props.ids[0] : null,\n        }\n    }\n\n    public componentDidMount(): void {\n        this._updateBasedOnProps(this.props)\n    }\n\n    public componentDidUpdate(prevProps: IVimNavigatorProps, prevState: IVimNavigatorState): void {\n        this._updateBasedOnProps(this.props)\n    }\n\n    public componentWillUnmount(): void {\n        this._releaseBinding()\n    }\n\n    public updateSelection = (id: string) => {\n        this.setState({ selectedId: id })\n    }\n\n    public render() {\n        const inputElement = (\n            <div className=\"input\">\n                <KeyboardInputView\n                    top={0}\n                    left={0}\n                    height={12}\n                    onActivate={this._activateEvent}\n                    onKeyDown={key => this._onKeyDown(key)}\n                    foregroundColor={\"white\"}\n                    fontFamily={\"Segoe UI\"}\n                    fontSize={\"12px\"}\n                    fontCharacterWidthInPixels={12}\n                />\n            </div>\n        )\n\n        return (\n            <div style={this.props.style}>\n                <NavigatorContainer>\n                    {this.props.render(this.state.selectedId, this.updateSelection)}\n                </NavigatorContainer>\n                {this.props.active ? inputElement : null}\n            </div>\n        )\n    }\n\n    private _onKeyDown(key: string): void {\n        if (this._activeBinding) {\n            this._activeBinding.input(key)\n        }\n    }\n\n    private _releaseBinding(): void {\n        if (this._activeBinding) {\n            this._activeBinding.release()\n            this._activeBinding = null\n        }\n    }\n\n    private _select(): void {\n        if (this.state.selectedId && this.props.active && this.props.onSelected) {\n            this.props.onSelected(this.state.selectedId)\n        }\n    }\n\n    private async _updateBasedOnProps(props: IVimNavigatorProps) {\n        if (props.active && !this._activeBinding) {\n            Log.info(\"[VimNavigator::activating]\")\n            this._releaseBinding()\n            this._activeBinding = getInstance().bindToMenu()\n\n            commandManager.registerCommand(\n                new CallbackCommand(\n                    \"select\",\n                    null,\n                    null,\n                    () => this._select(),\n                    () => this.props.active,\n                ),\n            )\n\n            this._activeBinding.onCursorMoved.subscribe(newValue => {\n                Log.info(\"[VimNavigator::onCursorMoved] - \" + newValue)\n                this._maybeUpdateSelection(newValue)\n            })\n\n            await this._activeBinding.setItems(this.props.ids, this.state.selectedId)\n            this._activateEvent.dispatch()\n        } else if (props.active && this._activeBinding) {\n            await this._activeBinding.setItems(this.props.ids, this.state.selectedId)\n        } else if (!props.active && this._activeBinding) {\n            this._releaseBinding()\n        }\n\n        if (props.idToSelect) {\n            this._maybeUpdateSelection(props.idToSelect)\n        }\n    }\n\n    private _maybeUpdateSelection(id: string) {\n        if (id !== this.state.selectedId) {\n            this.setState({ selectedId: id })\n\n            if (this.props.onSelectionChanged) {\n                this.props.onSelectionChanged(id)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/Visible.tsx",
    "content": "import * as React from \"react\"\n\nexport interface IVisibleProps {\n    visible: boolean\n}\n\nexport class Visible extends React.PureComponent<IVisibleProps, {}> {\n    public render(): null | JSX.Element {\n        if (this.props.visible) {\n            return React.Children.only(this.props.children)\n        } else {\n            return null\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/WildMenu.tsx",
    "content": "import * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport styled, { css } from \"styled-components\"\nimport { Icon } from \"./../../UI/Icon\"\n\nimport { fadeInAndDown } from \"./animations\"\nimport { boxShadow, withProps } from \"./common\"\n\nimport * as State from \"./../../Editor/NeovimEditor/NeovimEditorStore\"\n\nconst WildMenuList = styled.ul`\n    position: relative;\n    width: 75%;\n    max-height: 30em;\n    max-width: 900px;\n    animation: ${fadeInAndDown} 0.05s ease-in-out;\n    display: flex;\n    padding: 1em;\n    flex-direction: column;\n    box-sizing: border-box;\n    overflow: hidden;\n    background-color: ${p => p.theme[\"menu.background\"]};\n    color: ${p => p.theme[\"menu.foreground\"]};\n    ${boxShadow};\n`\nconst colors = css`\n    background-color: rgba(0, 0, 0, 0.2);\n    color: ${p => p.theme[\"menu.foreground\"]};\n`\nconst WildMenuItem = withProps<{ selected: boolean }>(styled.li)`\n    font-size: 1.1rem;\n    margin: 0.2em;\n    padding: 0.4em;\n    ${p => p.selected && boxShadow};\n    min-height: 1rem;\n    text-align: left;\n    overflow: hidden;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n    display: flex;\n    align-items: center;\n    justify-content: flex-start;\n    ${p => p.selected && colors};\n`\n\nconst WildMenuText = styled.span`\n    margin-left: 1rem;\n`\n\ninterface Props {\n    visible: boolean\n    options: string[]\n    selected: number\n}\n\ninterface State {\n    currentPage: number\n    itemsPerPage: number\n}\n\nclass WildMenu extends React.Component<Props, State> {\n    public state = {\n        currentPage: 1,\n        itemsPerPage: 10,\n    }\n\n    public componentWillReceiveProps(next: Props) {\n        if (next.selected !== this.props.selected) {\n            let currentPage = Math.floor(next.selected / this.state.itemsPerPage) + 1\n            currentPage = currentPage || 1\n            this.setState({ currentPage })\n        }\n    }\n\n    public render() {\n        const { visible } = this.props\n        const { currentItems, current } = this.calculateCurrentItems()\n\n        return (\n            visible && (\n                <WildMenuList>\n                    {currentItems &&\n                        currentItems.map((option, i) => (\n                            <WildMenuItem selected={i === current} key={option + i}>\n                                <span>\n                                    <Icon name=\"file-text\" />\n                                </span>\n                                <WildMenuText>{option}</WildMenuText>\n                            </WildMenuItem>\n                        ))}\n                </WildMenuList>\n            )\n        )\n    }\n\n    private calculateCurrentItems() {\n        const { options, selected } = this.props\n        const { currentPage, itemsPerPage } = this.state\n        const indexOfLastItem = currentPage * itemsPerPage\n        const indexOfFirstItem = indexOfLastItem - itemsPerPage\n        const currentItems = options.slice(indexOfFirstItem, indexOfLastItem)\n        const current = selected - itemsPerPage * (currentPage - 1)\n        return { current, currentItems }\n    }\n}\n\nconst mapStateToProps = ({ wildmenu: { options, visible, selected } }: State.IState) => {\n    return { options, visible, selected }\n}\n\nexport default connect(mapStateToProps)(WildMenu)\n"
  },
  {
    "path": "browser/src/UI/components/WindowSplitHost.tsx",
    "content": "/**\n * ISplitHost.tsx\n *\n * React component that hosts an IEditor implementation\n */\n\nimport * as React from \"react\"\n\nimport * as Oni from \"oni-api\"\n\nimport { RedErrorScreenView } from \"./../components/RedErrorScreen\"\n\nexport interface IWindowSplitHostProps {\n    split: Oni.IWindowSplit\n    id: string\n    containerClassName: string\n    isFocused: boolean\n    onClick: (evt: React.MouseEvent<HTMLElement>) => void\n}\n\nexport interface WindowSplitHostState {\n    errorInfo: ErrorInfo\n}\n\nexport interface ErrorInfo {\n    error: Error\n    info: React.ErrorInfo\n}\n\n/**\n * Component responsible for rendering an individual window split\n */\nexport class WindowSplitHost extends React.PureComponent<\n    IWindowSplitHostProps,\n    WindowSplitHostState\n> {\n    constructor(props: IWindowSplitHostProps) {\n        super(props)\n\n        this.state = {\n            errorInfo: null,\n        }\n\n        // Error\n        // React.ErrorInfo\n    }\n\n    public componentDidCatch(error: Error, info: React.ErrorInfo): void {\n        this.setState({\n            errorInfo: {\n                error,\n                info,\n            },\n        })\n    }\n\n    public render(): JSX.Element {\n        if (this.state.errorInfo) {\n            return (\n                <div className=\"container vertical full\">\n                    <RedErrorScreenView\n                        error={this.state.errorInfo.error}\n                        info={this.state.errorInfo.info}\n                    />\n                </div>\n            )\n        }\n\n        const className =\n            this.props.containerClassName + (this.props.isFocused ? \" focus\" : \" not-focused\")\n        return (\n            <div\n                id={this.props.id}\n                className=\"container vertical full\"\n                onClick={evt => (!this.props.isFocused ? this.props.onClick(evt) : null)}\n            >\n                <div className={className}>{this.props.split.render()}</div>\n            </div>\n        )\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/WindowSplits.tsx",
    "content": "/**\n * WindowSplits.tsx\n *\n * UI that hosts all the `Editor` instances\n */\n\nimport * as React from \"react\"\nimport { connect } from \"react-redux\"\nimport { AutoSizer } from \"react-virtualized\"\n\nimport { WindowSplitHost } from \"./WindowSplitHost\"\n\nimport {\n    IAugmentedSplitInfo,\n    ISplitInfo,\n    layoutFromSplitInfo,\n    leftDockSelector,\n    WindowManager,\n    WindowState,\n} from \"./../../Services/WindowManager\"\n\nimport { noop } from \"./../../Utility\"\n\nexport interface IWindowSplitsProps extends IWindowSplitsContainerProps {\n    activeSplitId: string\n    splitRoot: ISplitInfo<IAugmentedSplitInfo>\n    leftDock: IAugmentedSplitInfo[]\n}\n\nexport interface IWindowSplitsContainerProps {\n    windowManager: WindowManager\n}\n\nexport interface IDockProps {\n    activeSplitId: string\n    splits: IAugmentedSplitInfo[]\n}\n\nexport class Dock extends React.PureComponent<IDockProps, {}> {\n    public render(): JSX.Element {\n        const docks = this.props.splits.map((s, i) => {\n            return (\n                <div style={{ display: \"flex\", flexDirection: \"row\" }} key={s.id}>\n                    <WindowSplitHost\n                        key={i}\n                        id={s.id}\n                        containerClassName=\"split\"\n                        split={s}\n                        isFocused={this.props.activeSplitId === s.id}\n                        onClick={noop}\n                    />\n                    <div className=\"split-spacer vertical\" />\n                </div>\n            )\n        })\n\n        return <div className=\"dock container fixed horizontal\">{docks}</div>\n    }\n}\n\nexport interface IWindowSplitViewProps {\n    activeSplitId: string\n    split: ISplitInfo<IAugmentedSplitInfo>\n    windowManager: WindowManager\n}\n\nconst px = (num: number): string => num.toString() + \"px\"\n\nconst rectangleToStyleProperties = (\n    rect: Oni.Shapes.Rectangle,\n    totalHeight: number,\n): React.CSSProperties => {\n    const halfPadding = 3\n    const topPosition = rect.y === 0 ? 0 : Math.ceil(rect.y) + halfPadding\n\n    const bottomPadding = Math.ceil(rect.y + rect.height) >= totalHeight ? 0 : halfPadding * 2\n    return {\n        position: \"absolute\",\n        top: px(topPosition),\n        left: px(Math.ceil(rect.x) + halfPadding),\n        width: px(Math.floor(rect.width) - halfPadding * 2),\n        height: px(Math.floor(rect.height) - bottomPadding),\n    }\n}\nimport * as Oni from \"oni-api\"\n\nexport class WindowSplitView extends React.PureComponent<IWindowSplitViewProps, {}> {\n    public render(): JSX.Element {\n        const className = \"container horizontal full\"\n\n        // TODO: Add drag handles here to allow for resizing!\n        return (\n            <div className={className}>\n                <AutoSizer>\n                    {({ height, width }) => {\n                        const items = layoutFromSplitInfo(this.props.split, width, height)\n                        const vals: JSX.Element[] = Object.values(items).map(item => {\n                            const style = rectangleToStyleProperties(item.rectangle, height)\n                            return (\n                                <div style={style} key={item.split.id}>\n                                    <WindowSplitHost\n                                        id={item.split.id}\n                                        containerClassName=\"editor\"\n                                        split={item.split}\n                                        isFocused={this.props.activeSplitId === item.split.id}\n                                        onClick={() => {\n                                            this.props.windowManager.focusSplit(item.split.id)\n                                        }}\n                                    />\n                                </div>\n                            )\n                        })\n                        return <div style={{ position: \"relative\" }}>{vals}</div>\n                    }}\n                </AutoSizer>\n            </div>\n        )\n    }\n}\n\nexport class WindowSplitsView extends React.PureComponent<IWindowSplitsProps, {}> {\n    public render() {\n        if (!this.props.splitRoot) {\n            return null\n        }\n\n        const containerStyle: React.CSSProperties = {\n            display: \"flex\",\n            flexDirection: \"row\",\n            width: \"100%\",\n            height: \"100%\",\n        }\n\n        return (\n            <div style={containerStyle}>\n                <div className=\"container horizontal full\">\n                    <Dock splits={this.props.leftDock} activeSplitId={this.props.activeSplitId} />\n                    <WindowSplitView\n                        split={this.props.splitRoot}\n                        windowManager={this.props.windowManager}\n                        activeSplitId={this.props.activeSplitId}\n                    />\n                </div>\n            </div>\n        )\n    }\n}\n\nconst mapStateToProps = (\n    state: WindowState,\n    containerProps: IWindowSplitsContainerProps,\n): IWindowSplitsProps => {\n    return {\n        ...containerProps,\n        activeSplitId: state.focusedSplitId,\n        leftDock: leftDockSelector(state),\n        splitRoot: state.primarySplit,\n    }\n}\n\nexport const WindowSplits = connect(mapStateToProps)(WindowSplitsView)\n"
  },
  {
    "path": "browser/src/UI/components/WindowTitle.tsx",
    "content": "/**\n * WindowTitle.tsx\n *\n * Renders the title bar (OSX only)\n */\n\nimport * as React from \"react\"\n\nimport { connect } from \"react-redux\"\n\nimport { commandManager } from \"./../../Services/CommandManager\"\nimport * as State from \"./../Shell/ShellState\"\nimport styled from \"./common\"\n\nexport interface IWindowTitleViewProps {\n    visible: boolean\n    title: string\n}\n\nconst WindowTitleContainer = styled.div`\n    height: 22px;\n    padding: 3px 0;\n    line-height: 22px;\n    zoom: 1; /* Dont allow this to be impacted by zoom */\n    background-color: ${p => p.theme[\"title.background\"]};\n    color: ${p => p.theme[\"title.foreground\"]};\n    text-align: center;\n    -webkit-app-region: drag;\n    user-select: none;\n    pointer-events: all;\n`\n\nconst onDoubleClick = () => {\n    commandManager.executeCommand(\"oni.editor.maximize\")\n}\n\nexport const WindowTitleView = (props: IWindowTitleViewProps) => {\n    return (\n        props.visible && (\n            <WindowTitleContainer id=\"oni-titlebar\" onDoubleClick={onDoubleClick}>\n                {props.title}\n            </WindowTitleContainer>\n        )\n    )\n}\n\nexport interface IWindowTitleProps {\n    visible: boolean\n}\n\nexport const mapStateToProps = (\n    state: State.IState,\n    props: IWindowTitleProps,\n): IWindowTitleViewProps => {\n    return {\n        visible: props.visible && !state.isFullScreen,\n        title: state.windowTitle,\n    }\n}\n\nexport const WindowTitle = connect(mapStateToProps)(WindowTitleView)\n"
  },
  {
    "path": "browser/src/UI/components/WithWidth.tsx",
    "content": "import * as React from \"react\"\n\ninterface State {\n    width: number\n}\n\ninterface Props {\n    innerRef?: any\n    type?: any\n    passWidth?: any\n}\n\nexport default function withWidth(WrappedComponent: any) {\n    return class extends React.Component<Props, State> {\n        public static displayName = `WithWidth(${WrappedComponent.displayName ||\n            WrappedComponent.name})`\n        private observer: any\n        private _node: Element\n        constructor(props: Props) {\n            super(props)\n\n            this.state = {\n                width: null,\n            }\n        }\n\n        public componentWillMount() {\n            // tslint:disable-next-line\n            this.observer = new window[\"ResizeObserver\"](this.measure)\n        }\n\n        public render() {\n            const { innerRef, ...props } = this.props\n            return (\n                <WrappedComponent\n                    {...props}\n                    measureRef={this._handleRef}\n                    measure={this.measure}\n                    width={this.state.width}\n                />\n            )\n        }\n\n        private measure = ([entry]: any) => {\n            if (entry) {\n                this.setState({ width: entry.contentRect.width })\n            }\n        }\n\n        private _handleRef = (node: Element) => {\n            if (this.observer) {\n                if (node) {\n                    this.observer.observe(node)\n                } else {\n                    this.observer.disconnect(this._node)\n                }\n            }\n            this._node = node\n\n            if (typeof this.props.innerRef === \"function\") {\n                this.props.innerRef(node)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/UI/components/animations.ts",
    "content": "import { keyframes } from \"./common\"\n\nexport const fadeInAndDown = keyframes`\n    from {\n        opacity: 0;\n    }\n    to {\n        opacity: 1;\n    }\n`\n"
  },
  {
    "path": "browser/src/UI/components/common.less",
    "content": "// common.less\n\n// Font Size\n@font-size-normal: 1em;\n@font-size-small: 0.9em;\n\n// Colors\n@text-color: rgb(200, 200, 200);\n@text-color-dark: rgb(150, 150, 150);\n@text-color-highlight: rgb(240, 240, 240);\n@text-color-detail: rgb(100, 100, 100);\n\n@text-color-info: #6494ed;\n@text-color-success: #73c990;\n@text-color-warning: #e2c08d;\n@text-color-error: #fd6247;\n\n@shadow-color: rgba(0, 0, 0, 0.2);\n\n@background-color: rgb(40, 40, 40);\n@background-color-highlight: rgba(100, 200, 255, 0.2);\n@background-color-lighter: #3a3e44;\n@border-color: rgb(25, 25, 25);\n\n@bufferScrollBarSize: 7px;\n\n@component-padding: 10px;\n\n#host,\n.editor,\n.stack {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n}\n\n.split {\n    position: relative;\n    height: 100%;\n}\n\n.split-spacer {\n    box-shadow: inset rgba(0, 0, 0, 0.1) 0px 0px 3px 1px;\n    flex: 0 0 auto;\n\n    &.vertical {\n        height: 100%;\n        width: 6px;\n    }\n\n    &.horizontal {\n        width: 100%;\n        height: 6px;\n    }\n}\n\n// .split.focus, .editor.focus {\n//     z-index: 1;\n//     box-shadow: 1px 0px 8px 1px rgba(0, 0, 0, 0.1), -1px 0px 8px 1px rgba(0, 0, 0, 0.1);\n// }\n\n::-webkit-scrollbar-track {\n    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);\n    background-color: @background-color;\n}\n\n::-webkit-scrollbar {\n    width: 3px;\n    background-color: rgb(0, 0, 0);\n}\n\n::-webkit-scrollbar-thumb {\n    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);\n    background-color: @background-color-lighter;\n}\n\n.not-focused {\n    opacity: 0.8;\n}\n\n.focused {\n    opacity: 1;\n}\n\n.disable-mouse {\n    pointer-events: none;\n}\n\n.enable-mouse {\n    pointer-events: auto;\n}\n\n.container {\n    position: relative;\n\n    &.vertical {\n        display: flex;\n        flex-direction: column;\n    }\n\n    &.horizontal {\n        display: flex;\n        flex-direction: row;\n    }\n\n    &.full {\n        width: 100%;\n        height: 100%;\n        flex: 1 1 auto;\n    }\n\n    &.fixed {\n        flex: 0 0 auto;\n    }\n\n    &.center {\n        justify-content: center;\n        align-items: center;\n    }\n}\n\n.box-shadow-up-inset {\n    box-shadow: 0px -4px 20px 0px rgba(0, 0, 0, 0.2) inset;\n}\n\n.box-shadow {\n    box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n}\n\n.box-shadow-up {\n    box-shadow: 0 -8px 20px 0 rgba(0, 0, 0, 0.2);\n}\n\n@keyframes rotate {\n    from {\n        transform: rotateZ(0deg);\n    }\n    to {\n        transform: rotateZ(360deg);\n    }\n}\n\n.rotate-animation {\n    animation-name: rotate;\n    animation-duration: 4s;\n    animation-iteration-count: infinite;\n}\n\n.fade-enter {\n    opacity: 0;\n    transform: translateX(3px);\n}\n\n.fade-enter.fade-enter-active {\n    opacity: 1;\n    transform: translateX(0px);\n    transition-property: transform opacity;\n    transition-duration: 200ms;\n    transition-timing-function: ease-in;\n}\n\n.fade-exit {\n    opacity: 1;\n    transform: translateX(0px);\n}\n\n.fade-exit.fade-exit-active {\n    transform: translateX(-2px);\n    opacity: 0;\n    transition-property: transform opacity;\n    transition-duration: 150ms;\n    transition-timing-function: ease-in;\n}\n"
  },
  {
    "path": "browser/src/UI/components/common.ts",
    "content": "import * as Color from \"color\"\nimport * as styledComponents from \"styled-components\"\nimport {\n    FlattenInterpolation,\n    InterpolationValue,\n    ThemedStyledComponentsModule,\n    ThemeProps,\n} from \"styled-components\" // tslint:disable-line no-duplicate-imports\nimport { IThemeColors } from \"../../Services/Themes/ThemeManager\"\n\nexport const bufferScrollBarSize = \"7px\"\n\nconst {\n    default: styled,\n    css,\n    injectGlobal,\n    keyframes,\n    withTheme,\n    ThemeProvider,\n} = (styledComponents as ThemedStyledComponentsModule<any>) as ThemedStyledComponentsModule<\n    IThemeColors\n>\n\nexport type Css = InterpolationValue[] | Array<FlattenInterpolation<ThemeProps<IThemeColors>>>\n\ntype FlexDirection = \"flex-start\" | \"flex-end\" | \"center\" | \"space-between\"\n\nexport interface ContainerProps {\n    direction: \"horizontal\" | \"vertical\"\n    fullHeight?: boolean\n    fullWidth?: boolean\n    extension?: Css\n    justify?: FlexDirection\n    alignment?: FlexDirection\n}\n\nexport const Fixed = styled.div`\n    flex: 0 0 auto;\n`\n\nexport const Full = styled.div`\n    flex: 1 1 auto;\n`\n\nexport const Container = withProps<ContainerProps>(styled.div)`\n    display: flex;\n    flex-direction: ${p => (p.direction === \"vertical\" ? \"column\" : \"row\")};\n    ${p => (p.fullHeight ? \"height: 100%\" : \"\")};\n    ${p => (p.fullWidth ? \"width: 100%\" : \"\")};\n    ${p => (p.justify ? p.justify : \"\")};\n    ${p => (p.alignment ? p.alignment : \"\")}\n    ${p => p.extension};\n`\n\nexport const scrollbarStyles = css`\n    ${props =>\n        props.theme[\"scrollbar.track\"] &&\n        `&::-webkit-scrollbar-track {\n                background: ${props.theme[\"scrollbar.track\"]};\n        }`}\n    ${props =>\n        props.theme[\"scrollbar.thumb\"] &&\n        `&::-webkit-scrollbar-thumb {\n                background: ${props.theme[\"scrollbar.thumb\"]};\n        }`}\n    ${props =>\n        props.theme[\"scrollbar.thumb.hover\"] &&\n        `&::-webkit-scrollbar-thumb:hover {\n                background: ${props.theme[\"scrollbar.thumb.hover\"]};\n        }`};\n    `\n\nexport const Bold = styled.span`\n    font-weight: bold;\n`\n\nexport const Center = styled.div`\n    width: 100%;\n    height: 100%;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n`\n\nexport const stack = css`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n`\n\n// Layer is used to force webkit to promote the element to an individual layer.\n// This is used to tweak and control rendering performance, and not for layout\nexport const layer = css`\n    will-change: transform;\n`\n\nexport const StackLayer = styled<{ zIndex?: number | string }, \"div\">(\"div\")`\n    ${stack};\n    ${layer};\n    ${p => p.zIndex && `z-index: ${p.zIndex}`};\n`\n\ntype GetBorder = (\n    args: {\n        isSelected?: boolean\n        borderSize?: string\n        theme?: styledComponents.ThemeProps<IThemeColors>\n    },\n) => string\n\nexport const showScrollbarOnHover = css`\n    overflow: hidden;\n    &:hover {\n        overflow: overlay;\n    }\n`\n\nexport const getSelectedBorder: GetBorder = ({ isSelected, borderSize = \"1px\", theme }) =>\n    isSelected\n        ? `${borderSize} solid ${theme[\"highlight.mode.normal.background\"]}`\n        : `${borderSize} solid transparent`\n\nexport const sidebarItemSelected = css`\n    border: ${getSelectedBorder};\n`\n\nexport type StyledFunction<T> = styledComponents.ThemedStyledFunction<T, IThemeColors>\n\nexport function withProps<T, U extends HTMLElement = HTMLElement>(\n    styledFunction: StyledFunction<React.HTMLProps<U>>,\n): StyledFunction<T & React.HTMLProps<U>> {\n    return styledFunction\n}\n\nexport const pixel = (v: string | number): string => `${v}px`\n\nconst darken = (c: string, deg = 0.15) =>\n    Color(c)\n        .darken(deg)\n        .hex()\n        .toString()\n\nconst lighten = (c: string, deg = 0.25) =>\n    Color(c)\n        .lighten(deg)\n        .hex()\n\nconst boxShadow = css`\n    box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n`\n\nconst boxShadowUp = css`\n    box-shadow: 0 -8px 20px 0 rgba(0, 0, 0, 0.2);\n`\n\nconst boxShadowInset = css`\n    box-shadow: inset 0 4px 8px 2px rgba(0, 0, 0, 0.2);\n`\n\nconst boxShadowUpInset = css`\n    box-shadow: 0px -4px 20px 0px rgba(0, 0, 0, 0.2) inset;\n`\n\nconst enableMouse = css`\n    pointer-events: auto;\n`\n\nexport const OverlayWrapper = styled.div`\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n`\nconst tint = (base: string, mix: string, degree: number = 0.1) =>\n    Color(base)\n        .mix(Color(mix), 0.3)\n        .toString()\n\nconst fontSizeSmall = `font-size: 0.9em;`\n\nexport const textOverflow = css`\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n`\n\nconst fallBackFonts = `\n    Consolas,\n    Menlo,\n    Monaco,\n    Lucida Console,\n    Liberation Mono,\n    DejaVu Sans Mono,\n    Bitstream Vera Sans Mono,\n    Courier New,\n    monospace,\n    sans-serif\n`.trim()\n\n/**\n * Get a prop from the Oni theme\n *\n * @name propsInTheme\n * @function\n * @param {T} generic(theme object)\n * @param {string} ...paths the dot notation string path\n * @returns {string} the accessed prop or null\n */\nexport function propInTheme<T>(themeObject: T, ...paths: string[]): string {\n    return paths.reduce(\n        (targetObject, key) => (targetObject && targetObject[key] ? targetObject[key] : null),\n        themeObject,\n    )\n}\n\n/**\n *  **themeGet**\n *\n * helper method to pull a prop out of the theme and specify a fallback\n * the fallback can be a key in the theme object or a css style like \"red\" for color\n * the third argument is a key in the props object of the component which should represent\n * a boolean determining whether or no the default should be used\n * CREDIT: Styled-System\n */\nexport const themeGet = <T>(\n    paths: keyof IThemeColors,\n    fallback?: string,\n    shouldDefault?: keyof T,\n) => (props: OniStyledProps<T>) => {\n    if (shouldDefault && shouldDefault in props && !props[shouldDefault]) {\n        return propInTheme(props.theme, fallback)\n    }\n    return propInTheme(props.theme, paths) || propInTheme(props.theme, fallback) || fallback\n}\n\nexport type OniThemeProps = ThemeProps<IThemeColors>\nexport type OniStyledProps<T> = OniThemeProps & T\n\nexport {\n    css,\n    injectGlobal,\n    keyframes,\n    styled,\n    ThemeProvider,\n    withTheme,\n    tint,\n    boxShadow,\n    boxShadowUp,\n    boxShadowInset,\n    boxShadowUpInset,\n    enableMouse,\n    fontSizeSmall,\n    fallBackFonts,\n    darken,\n    lighten,\n    IThemeColors,\n}\n\nexport default styled\n"
  },
  {
    "path": "browser/src/Utility.ts",
    "content": "/**\n * Utility.ts\n *\n * Grab bag for functions that don't have another home.\n */\n\nimport * as fs from \"fs\"\nimport * as minimatch from \"minimatch\"\nimport * as path from \"path\"\n\nimport * as find from \"lodash/find\"\nimport * as isEqual from \"lodash/isEqual\"\nimport * as reduce from \"lodash/reduce\"\n\nimport { Observable } from \"rxjs/Observable\"\nimport { Subject } from \"rxjs/Subject\"\n\nimport * as JSON5 from \"json5\"\nimport { IDisposable, IEvent } from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nexport class Disposable implements IDisposable {\n    private _disposables: IDisposable[] = []\n    private _isDisposed: boolean = false\n\n    public get isDisposed(): boolean {\n        return this._isDisposed\n    }\n\n    public dispose(): void {\n        if (!this.isDisposed) {\n            this._isDisposed = true\n            this._disposables.forEach(disposable => disposable.dispose())\n            this._disposables = null\n        }\n    }\n\n    protected trackDisposable(disposable: IDisposable) {\n        this._disposables.push(disposable)\n    }\n}\n\nexport const asObservable = <T>(event: IEvent<T>): Observable<T> => {\n    const subject = new Subject<T>()\n\n    event.subscribe((val: T) => subject.next(val))\n\n    return subject\n}\n\n/**\n * Use a `node` require instead of a `webpack` require\n * The difference is that `webpack` require will bake the javascript\n * into the module. For most modules, we want the webpack behavior,\n * but for some (like node modules), we want to explicitly require them.\n */\n\nexport function nodeRequire(moduleName: string): any {\n    return window[\"require\"](moduleName) // tslint:disable-line\n}\n\nexport const EmptyArray: any[] = []\nexport const noop = () => {} // tslint:disable-line\n\nexport const normalizePath = (fileName: string) => fileName.split(\"\\\\\").join(\"/\")\n\n// String methods\n\n// ReplaceAll adapted from SO:\n// https://stackoverflow.com/questions/15604140/replace-multiple-strings-with-multiple-other-strings\nexport const replaceAll = (str: string, wordsToReplace: { [key: string]: string }) => {\n    const re = new RegExp(Object.keys(wordsToReplace).join(\"|\"), \"gi\")\n\n    return str.replace(re, matched => wordsToReplace[matched.toLowerCase()])\n}\n\nexport const flatMap = <T, U>(xs: T[], f: (item: T) => U[]): U[] =>\n    xs.reduce((x: U[], y: T) => [...x, ...f(y)], [])\n\nexport const diff = (newObject: any, oldObject: any) => {\n    // Return changed properties between newObject and oldObject\n    const updatedProperties = reduce(\n        newObject,\n        (result, value, key) => {\n            return isEqual(value, oldObject[key]) ? result : [...result, key]\n        },\n        [],\n    )\n\n    const keysInNewObject = Object.keys(newObject)\n    const deletedProperties = Object.keys(oldObject).filter(\n        key => keysInNewObject.indexOf(key) === -1,\n    )\n\n    return [...updatedProperties, ...deletedProperties]\n}\n\nexport const delay = (timeoutInMs: number = 100): Promise<void> => {\n    return new Promise<void>(r => window.setTimeout(() => r(), timeoutInMs))\n}\n\nexport const doesFileNameMatchGlobPatterns = (\n    fileName: string,\n    globPatterns: string[],\n): boolean => {\n    if (!fileName) {\n        return false\n    }\n\n    if (!globPatterns || !globPatterns.length) {\n        return false\n    }\n\n    for (const filePattern of globPatterns) {\n        if (minimatch(fileName, filePattern)) {\n            return true\n        }\n    }\n\n    return false\n}\n\nexport const getRootProjectFileFunc = (patternsToMatch: string[]) => {\n    const getFilesForDirectory = (fullPath: string): Promise<string[]> => {\n        return new Promise((res, rej) => {\n            fs.readdir(fullPath, (err, files) => {\n                if (err) {\n                    rej(err)\n                } else {\n                    res(files)\n                }\n            })\n        })\n    }\n\n    const getRootProjectFile = async (fullPath: string): Promise<string> => {\n        const parentDir = path.dirname(fullPath)\n\n        // Test for root folder\n        if (parentDir === fullPath) {\n            return Promise.reject(\"Unable to find root csproj file\")\n        }\n\n        const files = await getFilesForDirectory(fullPath)\n        const proj = find(files, f => doesFileNameMatchGlobPatterns(f, patternsToMatch))\n\n        if (proj) {\n            return fullPath\n        } else {\n            return getRootProjectFile(path.dirname(fullPath))\n        }\n    }\n\n    return getRootProjectFile\n}\n\nexport const requestIdleCallback = (fn: () => void): number => {\n    // tslint:disable-next-line\n    return window[\"requestIdleCallback\"](fn)\n}\n\nexport const isInRange = (line: number, column: number, range: types.Range): boolean => {\n    return (\n        line >= range.start.line &&\n        column >= range.start.character &&\n        line <= range.end.line &&\n        column <= range.end.character\n    )\n}\n\nexport const sleep = async (timeInMilliseconds: number): Promise<void> => {\n    return new Promise<void>(res => {\n        window.setTimeout(() => res(), timeInMilliseconds)\n    })\n}\n\nexport interface ICompletablePromise<T> {\n    promise: Promise<T>\n    resolve: (value?: T) => void\n    reject: (err?: Error) => void\n}\n\nexport const createCompletablePromise = <T>(): ICompletablePromise<T> => {\n    let resolve = null\n    let reject = null\n\n    const promise = new Promise<T>((res, rej) => {\n        resolve = res\n        reject = rej\n    })\n\n    return {\n        promise,\n        resolve,\n        reject,\n    }\n}\n\nexport const normalizeNewLines = (str: string): string => {\n    return str.split(\"\\r\\n\").join(\"\\n\")\n}\n\n/**\n * Helper function to ignore incoming values while a promise is waiting to complete\n * This is lossy, in that any input that comes in will be dropped while the promise\n * is in-progress.\n */\nexport function ignoreWhilePendingPromise<T, U>(\n    observable$: Observable<T>,\n    promiseFunction: (input: T) => Promise<U>,\n): Observable<U> {\n    // There must be a more 'RxJS' way to do this with `buffer` and `switchMap`,\n    // but I'm still amateur with this :)\n\n    const ret = new Subject<U>()\n\n    let pendingInputs: T[] = []\n    let isPromiseInFlight = false\n\n    const promiseExecutor = () => {\n        if (pendingInputs.length > 0) {\n            const latestValue = pendingInputs[pendingInputs.length - 1]\n            pendingInputs = []\n\n            isPromiseInFlight = true\n            promiseFunction(latestValue).then(\n                v => {\n                    ret.next(v)\n\n                    isPromiseInFlight = false\n                    promiseExecutor()\n                },\n                err => {\n                    isPromiseInFlight = false\n                    promiseExecutor()\n                    throw err\n                },\n            )\n        }\n    }\n\n    observable$.subscribe(\n        (val: T) => {\n            pendingInputs.push(val)\n\n            if (!isPromiseInFlight) {\n                promiseExecutor()\n            }\n        },\n        err => ret.error(err),\n        () => ret.complete(),\n    )\n\n    return ret\n}\n\nexport const parseJson5 = <T>(text: string): T => {\n    return JSON5.parse(text) as T\n}\n\nexport const formatDate = (dateStr: string) => {\n    const options: Intl.DateTimeFormatOptions = {\n        weekday: \"long\",\n        year: \"numeric\",\n        month: \"long\",\n        day: \"numeric\",\n        hour: \"numeric\",\n        minute: \"numeric\",\n    }\n    const date = new Date(dateStr)\n    return date.toLocaleDateString(\"en-US\", options)\n}\n\n// Courtesy of https://stackoverflow.com/questions/3177836\n// /how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site\nexport const getTimeSince = (date: Date) => {\n    const currentDate = Date.now()\n    const seconds = Math.floor((currentDate - date.getTime()) / 1000)\n    let interval = Math.floor(seconds / 31536000)\n\n    if (interval > 1) {\n        return interval + \" years\"\n    }\n    interval = Math.floor(seconds / 2592000)\n    if (interval > 1) {\n        return interval + \" months\"\n    }\n    interval = Math.floor(seconds / 86400)\n    if (interval > 1) {\n        return interval + \" days\"\n    }\n    interval = Math.floor(seconds / 3600)\n    if (interval > 1) {\n        return interval + \" hours\"\n    }\n    interval = Math.floor(seconds / 60)\n    if (interval > 1) {\n        return interval + \" minutes\"\n    }\n    return Math.floor(seconds) + \" seconds\"\n}\n\n/*\n * get\n * allows for safe deeply nested object access\n */\nexport function get<T>(obj: T, ...paths: string[]): string {\n    return paths\n        .join(\".\")\n        .split(\".\")\n        .reduce((a, b) => (a && a[b] ? a[b] : null), obj)\n}\n\nexport function prettyPrint<T extends object>(item: T, spacing = 2) {\n    // tslint:disable-next-line\n    console.log(JSON.stringify(item, null, spacing))\n}\n"
  },
  {
    "path": "browser/src/index.tsx",
    "content": "/**\n * index.tsx\n *\n * Entry point for the BrowserWindow process\n */\n\nimport { ipcRenderer } from \"electron\"\n\nimport * as App from \"./App\"\n\nipcRenderer.on(\"init\", (_evt: any, message: any) => {\n    process.chdir(message.workingDirectory)\n    App.start(message.args)\n})\n\nipcRenderer.on(\"execute-command\", async (_evt: any, command: string, arg?: any) => {\n    const { commandManager } = await import(\"./Services/CommandManager\")\n    commandManager.executeCommand(command, arg)\n})\n"
  },
  {
    "path": "browser/src/neovim/CommandContext.ts",
    "content": "/**\n * CommandContext\n *\n * This is a definition of the object that Neovim passes up\n * as part of running commands.\n */\n\nexport interface CommandContext {\n    command: string\n    args: string[]\n}\n"
  },
  {
    "path": "browser/src/neovim/EventContext.ts",
    "content": "/**\n * EventContext\n *\n * This is a definition of the object that Neovim passes up\n * as part of autocommands.\n */\n\nexport interface EventContext {\n    bufferFullPath: string\n    bufferTotalLines: number\n    bufferNumber: number\n    modified: boolean\n    hidden: boolean\n    listed: boolean\n    version: number\n    line: number\n    /**\n     * Column within the buffer\n     */\n    column: number\n    byte: number\n    filetype: string\n    tabNumber: number\n    windowNumber: number\n    wincol: number\n    winline: number\n    windowTopLine: number\n    windowBottomLine: number\n    windowWidth: number\n    windowHeight: number\n    tabstop: number\n    shiftwidth: number\n    comments: string\n}\n\nexport interface InactiveBufferContext {\n    bufferNumber: number\n    bufferFullPath: string\n    filetype: string\n    buftype: string\n    modified: boolean\n    hidden: boolean\n    listed: boolean\n    version: number\n}\n\nexport interface BufferEventContext {\n    current: EventContext\n    existingBuffers: InactiveBufferContext[]\n}\n"
  },
  {
    "path": "browser/src/neovim/MsgPack.ts",
    "content": "/**\n * MsgPack.ts\n *\n * Definition of MsgPack types for Neovim\n */\n\nimport * as msgpackLite from \"msgpack-lite\"\n\nexport class MsgPackObjectReference {\n    public id: string\n}\n\nexport class NeovimBufferReference extends MsgPackObjectReference {}\nexport class NeovimWindowReference extends MsgPackObjectReference {}\nexport class NeovimTabReference extends MsgPackObjectReference {}\n\nexport const Pack = (reference: MsgPackObjectReference) => {\n    return msgpackLite.encode(reference.id)\n}\n\nexport const Unpack = (rawData: any, msgPackObject: MsgPackObjectReference) => {\n    const id = msgpackLite.decode(rawData)\n    msgPackObject.id = id\n    return msgPackObject\n}\n\nexport const UnpackBuffer = (rawData: any) => Unpack(rawData, new NeovimBufferReference())\nexport const UnpackTab = (rawData: any) => Unpack(rawData, new NeovimTabReference())\nexport const UnpackWindow = (rawData: any) => Unpack(rawData, new NeovimWindowReference())\n"
  },
  {
    "path": "browser/src/neovim/NeovimAutoCommands.ts",
    "content": "/**\n * NeovimAutoCommands.ts\n *\n * Strongly typed interface to Neovim's autocommands\n * - To add a new autocommand, make sure it is registered in `init.vim` in the `OniEventListeners` augroup\n */\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { BufferEventContext, EventContext } from \"./EventContext\"\nimport { NeovimInstance } from \"./NeovimInstance\"\n\nexport interface INeovimAutoCommands {\n    // Autocommands\n    onBufEnter: IEvent<BufferEventContext>\n    onBufWipeout: IEvent<BufferEventContext>\n    onBufWinEnter: IEvent<BufferEventContext>\n    onBufDelete: IEvent<BufferEventContext>\n    onBufUnload: IEvent<BufferEventContext>\n    onBufWritePost: IEvent<EventContext>\n    onFileTypeChanged: IEvent<EventContext>\n    onWinEnter: IEvent<EventContext>\n    onCursorMoved: IEvent<EventContext>\n    onCursorMovedI: IEvent<EventContext>\n    onVimResized: IEvent<EventContext>\n\n    executeAutoCommand(autoCommand: string): Promise<void>\n}\n\nexport class NeovimAutoCommands {\n    // Autocommand events\n    private _nameToEvent: { [key: string]: Event<EventContext | BufferEventContext> }\n    private _onBufEnterEvent = new Event<BufferEventContext>()\n    private _onBufWritePostEvent = new Event<EventContext>()\n    private _onBufWipeoutEvent = new Event<BufferEventContext>()\n    private _onBufDeleteEvent = new Event<BufferEventContext>()\n    private _onBufUnloadEvent = new Event<BufferEventContext>()\n    private _onBufWinEnterEvent = new Event<BufferEventContext>()\n    private _onFileTypeChangedEvent = new Event<EventContext>()\n    private _onWinEnterEvent = new Event<EventContext>()\n    private _onCursorMovedEvent = new Event<EventContext>()\n    private _onCursorMovedIEvent = new Event<EventContext>()\n    private _onVimResizedEvent = new Event<EventContext>()\n\n    public get onBufEnter(): IEvent<BufferEventContext> {\n        return this._onBufEnterEvent\n    }\n\n    public get onBufDelete(): IEvent<BufferEventContext> {\n        return this._onBufDeleteEvent\n    }\n\n    public get onBufUnload(): IEvent<BufferEventContext> {\n        return this._onBufUnloadEvent\n    }\n\n    public get onBufWritePost(): IEvent<EventContext> {\n        return this._onBufWritePostEvent\n    }\n\n    public get onBufWinEnter(): IEvent<BufferEventContext> {\n        return this._onBufWinEnterEvent\n    }\n\n    public get onBufWipeout(): IEvent<BufferEventContext> {\n        return this._onBufWipeoutEvent\n    }\n\n    public get onFileTypeChanged(): IEvent<EventContext> {\n        return this._onFileTypeChangedEvent\n    }\n\n    public get onWinEnter(): IEvent<EventContext> {\n        return this._onWinEnterEvent\n    }\n\n    public get onCursorMoved(): IEvent<EventContext> {\n        return this._onCursorMovedEvent\n    }\n\n    public get onCursorMovedI(): IEvent<EventContext> {\n        return this._onCursorMovedIEvent\n    }\n\n    public get onVimResized(): IEvent<EventContext> {\n        return this._onVimResizedEvent\n    }\n\n    constructor(private _neovimInstance: NeovimInstance) {\n        this._nameToEvent = {\n            BufEnter: this._onBufEnterEvent,\n            BufWritePost: this._onBufWritePostEvent,\n            BufWinEnter: this._onBufWinEnterEvent,\n            BufWipeout: this._onBufWipeoutEvent,\n            BufUnload: this._onBufUnloadEvent,\n            BufDelete: this._onBufDeleteEvent,\n            CursorMoved: this._onCursorMovedEvent,\n            CursorMovedI: this._onCursorMovedIEvent,\n            FileType: this._onFileTypeChangedEvent,\n            WinEnter: this._onWinEnterEvent,\n            VimResized: this._onVimResizedEvent,\n        }\n    }\n\n    public notifyAutocommand(autoCommandName: string, context: EventContext): void {\n        const evt = this._nameToEvent[autoCommandName]\n\n        if (!evt) {\n            return\n        }\n\n        evt.dispatch(context)\n    }\n\n    public async executeAutoCommand(autoCommand: string): Promise<void> {\n        if (!this._neovimInstance.isInitialized) {\n            return\n        }\n\n        const doesAutoCommandExist = await this._neovimInstance.eval(`exists('#${autoCommand}')`)\n\n        if (doesAutoCommandExist) {\n            await this._neovimInstance.command(`doautocmd <nomodeline> ${autoCommand}`)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/NeovimBufferUpdateManager.ts",
    "content": "/**\n * BufferUpdateManager.ts\n *\n * Helper for linking Neovim buffer updates with the `BufferChanged` event\n */\n\nimport * as os from \"os\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { Configuration } from \"./../Services/Configuration\"\n\nimport { EventContext, NeovimInstance } from \"./../neovim\"\n\nexport interface INeovimBufferUpdate {\n    eventContext: EventContext\n    contentChanges: types.TextDocumentContentChangeEvent[]\n}\n\nexport class NeovimBufferUpdateManager {\n    private _onBufferUpdateEvent = new Event<INeovimBufferUpdate>()\n    private _lastEventContext: EventContext\n    private _lastMode: string\n\n    private _isRequestInProgress: boolean = false\n    private _queuedRequest: EventContext\n\n    public get onBufferUpdate(): IEvent<INeovimBufferUpdate> {\n        return this._onBufferUpdateEvent\n    }\n\n    constructor(private _configuration: Configuration, private _neovimInstance: NeovimInstance) {}\n\n    public async notifyFullBufferUpdate(eventContext: EventContext): Promise<void> {\n        if (!this._shouldSubscribeToUpdates(eventContext)) {\n            return\n        }\n\n        this._doFullUpdate(eventContext)\n    }\n\n    public async notifyModeChanged(newMode: string): Promise<void> {\n        const shouldUpdate = newMode === \"insert\" && this._lastMode !== \"insert\"\n        this._lastMode = newMode\n\n        if (!shouldUpdate) {\n            return\n        }\n\n        const eventContext = await this._neovimInstance.getContext()\n\n        if (!this._shouldSubscribeToUpdates(eventContext)) {\n            return\n        }\n\n        this._doFullUpdate(eventContext)\n    }\n\n    public notifyIncrementalBufferUpdate(\n        eventContext: EventContext,\n        lineNumber: number,\n        lineContents: string,\n    ): void {\n        if (!this._shouldSubscribeToUpdates(eventContext)) {\n            return\n        }\n\n        const shouldDoFullUpdate = this._shouldDoFullUpdate(eventContext, this._lastEventContext)\n\n        if (shouldDoFullUpdate) {\n            this._doFullUpdate(eventContext)\n            return\n        }\n\n        const changedLine = lineContents\n\n        const update: INeovimBufferUpdate = {\n            eventContext,\n            contentChanges: [\n                {\n                    range: types.Range.create(lineNumber - 1, 0, lineNumber, 0),\n                    text: changedLine + os.EOL,\n                },\n            ],\n        }\n\n        this._onBufferUpdateEvent.dispatch(update)\n    }\n\n    private async _doFullUpdate(eventContext: EventContext): Promise<void> {\n        if (this._isRequestInProgress) {\n            this._queuedRequest = eventContext\n            return\n        }\n\n        this._isRequestInProgress = true\n        const bufferLines = await this._neovimInstance.request<string[]>(\"nvim_buf_get_lines\", [\n            eventContext.bufferNumber,\n            0,\n            eventContext.bufferTotalLines,\n            false,\n        ])\n        this._isRequestInProgress = false\n\n        const update: INeovimBufferUpdate = {\n            eventContext,\n            contentChanges: [{ text: bufferLines.join(os.EOL) }],\n        }\n\n        this._lastEventContext = eventContext\n        this._onBufferUpdateEvent.dispatch(update)\n\n        // Is there a queued request?\n        if (this._queuedRequest) {\n            const req = this._queuedRequest\n            this._queuedRequest = null\n            this._doFullUpdate(req)\n        }\n    }\n\n    private _shouldDoFullUpdate(\n        currentContext: EventContext,\n        previousContext: EventContext,\n    ): boolean {\n        if (!previousContext) {\n            return true\n        }\n\n        if (currentContext.bufferFullPath !== previousContext.bufferFullPath) {\n            return true\n        }\n\n        if (currentContext.bufferTotalLines !== previousContext.bufferTotalLines) {\n            return true\n        }\n\n        return false\n    }\n\n    private _shouldSubscribeToUpdates(context: EventContext): boolean {\n        if (\n            context.bufferTotalLines >\n            this._configuration.getValue(\"editor.maxLinesForLanguageServices\")\n        ) {\n            return false\n        }\n\n        return true\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/NeovimInstance.ts",
    "content": "import { EventEmitter } from \"events\"\nimport { pathExistsSync } from \"fs-extra\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport * as Performance from \"./../Performance\"\nimport { CommandContext } from \"./CommandContext\"\nimport { EventContext } from \"./EventContext\"\n\nimport { addDefaultUnitIfNeeded, measureFont } from \"./../Font\"\nimport * as Platform from \"./../Platform\"\nimport { Configuration } from \"./../Services/Configuration\"\n\nimport * as Actions from \"./actions\"\nimport { NeovimBufferReference } from \"./MsgPack\"\nimport { INeovimAutoCommands, NeovimAutoCommands } from \"./NeovimAutoCommands\"\nimport { INeovimMarks, NeovimMarks } from \"./NeovimMarks\"\nimport { INeovimStartOptions, startNeovim } from \"./NeovimProcessSpawner\"\nimport { IQuickFixList, QuickFixList } from \"./QuickFix\"\nimport { IPixelPosition, IPosition } from \"./Screen\"\nimport { Session } from \"./Session\"\n\nimport { PromiseQueue } from \"./../Services/Language/PromiseQueue\"\nimport { TokenColor } from \"./../Services/TokenColors\"\nimport { INeovimBufferUpdate, NeovimBufferUpdateManager } from \"./NeovimBufferUpdateManager\"\nimport { NeovimTokenColorSynchronizer } from \"./NeovimTokenColorSynchronizer\"\n\nimport {\n    IVimHighlight,\n    VimHighlightToDefaultScope,\n    vimHighlightToTokenColorStyle,\n} from \"./VimHighlights\"\n\nexport interface INeovimYankInfo {\n    operator: string\n    regcontents: string[]\n    regname: string\n    regtype: string\n}\n\nexport interface INeovimApiVersion {\n    major: number\n    minor: number\n    patch: number\n}\n\nexport interface IFullBufferUpdateEvent {\n    context: EventContext\n    bufferLines: string[]\n}\n\nexport interface IIncrementalBufferUpdateEvent {\n    context: EventContext\n    lineNumber: number\n    lineContents: string\n}\n\nexport interface INeovimCompletionItem {\n    word: string\n    kind: string\n    menu: string\n    info: string\n}\n\nexport interface INeovimCompletionInfo {\n    items: INeovimCompletionItem[]\n    selectedIndex: number\n    row: number\n    col: number\n}\n\nexport type CommandLineContent = [any, string]\n\nexport type MapcheckModes = \"n\" | \"v\" | \"i\"\n\ninterface IMapping {\n    key: string\n    mode: MapcheckModes\n}\n\nexport interface INeovimCommandLineShowEvent {\n    content: CommandLineContent[]\n    pos: number\n    firstc: string\n    prompt: string\n    indent: number\n    level: number\n}\n\nexport interface IWildMenuShowEvent {\n    options: string[]\n}\n\nexport interface IWildMenuSelectEvent {\n    selected: any\n}\n\nexport interface INeovimCommandLineSetCursorPosition {\n    pos: number\n    level: number\n}\n\nexport interface IMessageInfo {\n    severity: \"warn\" | \"error\" | \"info\"\n    title: string\n    details: string\n}\n\n// Limit for the number of lines to handle buffer updates\n// If the file is too large, it ends up being too much traffic\n// between Neovim <-> Oni <-> Language Servers - so\n// set a hard limit. In the future, if need be, this could be\n// moved to a configuration setting.\nexport const MAX_LINES_FOR_BUFFER_UPDATE = 5000\n\nexport type NeovimEventHandler = (...args: any[]) => void\n\nexport interface INeovimEvent {\n    eventName: string\n    eventContext: EventContext\n}\n\nexport interface INeovimInstance {\n    cursorPosition: IPosition\n    quickFix: IQuickFixList\n\n    // Events\n    onYank: IEvent<INeovimYankInfo>\n\n    onBufferUpdate: IEvent<INeovimBufferUpdate>\n\n    onRedrawComplete: IEvent<void>\n\n    onScroll: IEvent<EventContext>\n\n    onTitleChanged: IEvent<string>\n\n    // When an OniCommand is requested, ie :OniCommand(\"quickOpen.show\")\n    onOniCommand: IEvent<CommandContext>\n\n    onHidePopupMenu: IEvent<void>\n    onShowPopupMenu: IEvent<INeovimCompletionInfo>\n\n    onColorsChanged: IEvent<void>\n\n    onCommandLineShow: IEvent<INeovimCommandLineShowEvent>\n    onCommandLineHide: IEvent<void>\n    onCommandLineSetCursorPosition: IEvent<INeovimCommandLineSetCursorPosition>\n\n    onMessage: IEvent<IMessageInfo>\n\n    onVimEvent: IEvent<INeovimEvent>\n\n    autoCommands: INeovimAutoCommands\n    marks: INeovimMarks\n\n    screenToPixels(row: number, col: number): IPixelPosition\n\n    /**\n     * Supply input (keyboard/mouse) to Neovim\n     */\n    input(inputString: string): Promise<void>\n\n    /**\n     * Call a VimL function\n     */\n    callFunction(functionName: string, args: any[]): Promise<any>\n\n    /**\n     * Change the working directory of Neovim\n     */\n    chdir(directoryPath: string): Promise<any>\n\n    /**\n     * Execute a VimL command\n     */\n    command(command: string): Promise<any>\n\n    /**\n     * Evaluate a VimL block\n     */\n    eval(expression: string): Promise<any>\n\n    // TODO:\n    // - Refactor remaining events into strongly typed events, as part of the interface\n    on(event: string, handler: NeovimEventHandler): void\n\n    setFont(fontFamily: string, fontSize: string, fontWeight: string, linePadding: number): void\n\n    getBufferIds(): Promise<number[]>\n\n    getApiVersion(): Promise<INeovimApiVersion>\n\n    open(fileName: string): Promise<void>\n    openInitVim(): Promise<void>\n}\n\n/**\n * Integration with NeoVim API\n */\nexport class NeovimInstance extends EventEmitter implements INeovimInstance {\n    private _neovim: Session\n    private _isDisposed: boolean = false\n    private _initPromise: Promise<void>\n    private _isLeaving: boolean\n    private _currentVimDirectory: string\n\n    private _inputQueue: PromiseQueue = new PromiseQueue()\n\n    private _configuration: Configuration\n    private _autoCommands: NeovimAutoCommands\n\n    private _fontFamily: string\n    private _fontSize: string\n    private _fontWeight: string\n    private _fontWidthInPixels: number\n    private _fontHeightInPixels: number\n\n    private _lastHeightInPixels: number\n    private _lastWidthInPixels: number\n\n    private _rows: number\n    private _cols: number\n\n    private _quickFix: QuickFixList\n    private _marks: NeovimMarks\n    private _initComplete: boolean\n\n    private _onDirectoryChanged = new Event<string>()\n    private _onErrorEvent = new Event<Error | string>()\n    private _onYank = new Event<INeovimYankInfo>()\n    private _onOniCommand = new Event<CommandContext>()\n    private _onRedrawComplete = new Event<void>()\n    private _onScroll = new Event<EventContext>()\n    private _onTitleChanged = new Event<string>()\n    private _onModeChanged = new Event<Oni.Vim.Mode>()\n    private _onHidePopupMenu = new Event<void>()\n    private _onShowPopupMenu = new Event<INeovimCompletionInfo>()\n    private _onSelectPopupMenu = new Event<number>()\n    private _onLeave = new Event<void>()\n    private _onMessage = new Event<IMessageInfo>()\n\n    private _onColorsChanged = new Event<void>()\n\n    private _onCommandLineShowEvent = new Event<INeovimCommandLineShowEvent>()\n    private _onCommandLineHideEvent = new Event<void>()\n    private _onCommandLineSetCursorPositionEvent = new Event<INeovimCommandLineSetCursorPosition>()\n    private _onVimEvent = new Event<INeovimEvent>()\n    private _onWildMenuHideEvent = new Event<void>()\n    private _onWildMenuSelectEvent = new Event<IWildMenuSelectEvent>()\n    private _onWildMenuShowEvent = new Event<IWildMenuShowEvent>()\n    private _bufferUpdateManager: NeovimBufferUpdateManager\n    private _tokenColorSynchronizer: NeovimTokenColorSynchronizer\n\n    private _pendingScrollTimeout: number | null = null\n\n    private _disposables: IDisposable[] = []\n\n    public get isInitialized(): boolean {\n        return this._initComplete\n    }\n\n    public get quickFix(): IQuickFixList {\n        return this._quickFix\n    }\n\n    public get onBufferUpdate(): IEvent<INeovimBufferUpdate> {\n        return this._bufferUpdateManager.onBufferUpdate\n    }\n\n    public get onColorsChanged(): IEvent<void> {\n        return this._onColorsChanged\n    }\n\n    public get onDirectoryChanged(): IEvent<string> {\n        return this._onDirectoryChanged\n    }\n\n    public get onError(): IEvent<Error | string> {\n        return this._onErrorEvent\n    }\n\n    public get onLeave(): IEvent<void> {\n        return this._onLeave\n    }\n\n    public get onMessage(): IEvent<IMessageInfo> {\n        return this._onMessage\n    }\n\n    public get onModeChanged(): IEvent<Oni.Vim.Mode> {\n        return this._onModeChanged\n    }\n\n    public get onOniCommand(): IEvent<CommandContext> {\n        return this._onOniCommand\n    }\n\n    public get onRedrawComplete(): IEvent<void> {\n        return this._onRedrawComplete\n    }\n\n    public get onScroll(): IEvent<EventContext> {\n        return this._onScroll\n    }\n\n    public get onTitleChanged(): IEvent<string> {\n        return this._onTitleChanged\n    }\n\n    public get onHidePopupMenu(): IEvent<void> {\n        return this._onHidePopupMenu\n    }\n\n    public get onSelectPopupMenu(): IEvent<number> {\n        return this._onSelectPopupMenu\n    }\n\n    public get onShowPopupMenu(): IEvent<INeovimCompletionInfo> {\n        return this._onShowPopupMenu\n    }\n\n    public get onCommandLineShow(): IEvent<INeovimCommandLineShowEvent> {\n        return this._onCommandLineShowEvent\n    }\n\n    public get onCommandLineHide(): IEvent<void> {\n        return this._onCommandLineHideEvent\n    }\n\n    public get onCommandLineSetCursorPosition(): IEvent<INeovimCommandLineSetCursorPosition> {\n        return this._onCommandLineSetCursorPositionEvent\n    }\n\n    public get onVimEvent(): IEvent<INeovimEvent> {\n        return this._onVimEvent\n    }\n\n    public get onWildMenuShow(): IEvent<IWildMenuShowEvent> {\n        return this._onWildMenuShowEvent\n    }\n\n    public get onWildMenuSelect(): IEvent<IWildMenuSelectEvent> {\n        return this._onWildMenuSelectEvent\n    }\n\n    public get onWildMenuHide(): IEvent<void> {\n        return this._onWildMenuHideEvent\n    }\n\n    public get onYank(): IEvent<INeovimYankInfo> {\n        return this._onYank\n    }\n\n    public get autoCommands(): INeovimAutoCommands {\n        return this._autoCommands\n    }\n\n    public get marks(): INeovimMarks {\n        return this._marks\n    }\n\n    public get tokenColorSynchronizer(): NeovimTokenColorSynchronizer {\n        return this._tokenColorSynchronizer\n    }\n\n    public get currentVimDirectory(): string {\n        return this._currentVimDirectory\n    }\n\n    constructor(widthInPixels: number, heightInPixels: number, configuration: Configuration) {\n        super()\n        this._configuration = configuration\n        this._fontFamily = this._configuration.getValue(\"editor.fontFamily\")\n        this._fontSize = addDefaultUnitIfNeeded(this._configuration.getValue(\"editor.fontSize\"))\n        this._fontWeight = this._configuration.getValue(\"editor.fontWeight\")\n\n        this._lastWidthInPixels = widthInPixels\n        this._lastHeightInPixels = heightInPixels\n\n        this._quickFix = new QuickFixList(this)\n        this._autoCommands = new NeovimAutoCommands(this)\n        this._marks = new NeovimMarks(this)\n        this._tokenColorSynchronizer = new NeovimTokenColorSynchronizer(this)\n\n        this._bufferUpdateManager = new NeovimBufferUpdateManager(this._configuration, this)\n\n        const s1 = this._onModeChanged.subscribe(newMode => {\n            this._bufferUpdateManager.notifyModeChanged(newMode)\n        })\n\n        const dispatchScroll = () => this._dispatchScrollEvent()\n\n        const s2 = this._autoCommands.onCursorMoved.subscribe(dispatchScroll)\n        const s3 = this._autoCommands.onCursorMovedI.subscribe(dispatchScroll)\n\n        this._disposables = [s1, s2, s3]\n    }\n\n    public dispose(): void {\n        if (this._neovim) {\n            this._neovim.dispose()\n            this._neovim = null\n        }\n\n        if (this._disposables) {\n            this._disposables.forEach(d => d.dispose())\n        }\n\n        this._configuration = null\n    }\n\n    public async chdir(directoryPath: string): Promise<void> {\n        await this.command(`cd! ${directoryPath}`)\n    }\n\n    public async checkUserMapping({ key, mode = \"n\" }: IMapping) {\n        const mapping: string = await this.callFunction(\"mapcheck\", [key, mode])\n        return { key, mapping }\n    }\n\n    public async checkUserMappings(keys: IMapping[]) {\n        const mappings = await Promise.all(keys.map(this.checkUserMapping))\n        return mappings\n    }\n\n    // Make a direct request against the msgpack API\n    public async request<T>(request: string, args: any[]): Promise<T> {\n        if (!this._neovim || this._neovim.isDisposed) {\n            Log.warn(\"[NeovimInstance::request] Attempted to request on a disposed neovim instance\")\n            return null\n        }\n\n        return this._neovim.request<T>(request, args)\n    }\n\n    public async getContext(): Promise<EventContext> {\n        return this.callFunction(\"OniGetContext\", [])\n    }\n\n    public async start(startOptions?: INeovimStartOptions): Promise<void> {\n        Performance.startMeasure(\"NeovimInstance.Start\")\n        this._initPromise = startNeovim(startOptions).then(async nv => {\n            Log.info(\"NeovimInstance: Neovim started\")\n\n            // Workaround for issue where UI\n            // can fail to attach if there is a UI-blocking error\n            // nv.input(\"<ESC>\")\n\n            this._neovim = nv\n\n            this._neovim.on(\"error\", (err: Error) => {\n                this._onError(err)\n            })\n\n            this._neovim.on(\"notification\", (method: any, args: any) =>\n                this._onNotification(method, args),\n            )\n\n            this._neovim.on(\"request\", (method: any, _args: any, _resp: any) => {\n                Log.warn(\"Unhandled request: \" + method)\n            })\n\n            this._neovim.on(\"disconnect\", () => {\n                if (!this._isLeaving) {\n                    this._onError(\n                        \"Neovim disconnected. This likely means that the Neovim process crashed.\",\n                    )\n                }\n            })\n\n            await this._checkAndFixIfBlocked()\n\n            const size = this._getSize()\n            this._rows = size.rows\n            this._cols = size.cols\n\n            // Workaround for bug in neovim/node-client\n            // The 'uiAttach' method overrides the new 'nvim_ui_attach' method\n            Performance.startMeasure(\"NeovimInstance.Start.Attach\")\n            return this._attachUI(size.cols, size.rows).then(\n                async () => {\n                    Log.info(\"Attach success\")\n                    Performance.endMeasure(\"NeovimInstance.Start.Attach\")\n\n                    // TODO: #702 - Batch these calls via `nvim_call_atomic`\n                    // Override completeopt so Oni works correctly with external popupmenu\n                    // await this.command(\"set completeopt=longest,menu\")\n\n                    // set title after attaching listeners so we can get the initial title\n                    await this.command(\"set title\")\n\n                    Performance.endMeasure(\"NeovimInstance.Start\")\n\n                    this._initComplete = true\n                },\n                (err: any) => {\n                    this._onError(err)\n                    this._initComplete = true\n                },\n            )\n        })\n\n        return this._initPromise\n    }\n\n    public async getTokenColors(): Promise<TokenColor[]> {\n        const vimHighlights = Object.keys(VimHighlightToDefaultScope)\n        const atomicCalls = vimHighlights.map(highlight => {\n            return [\"nvim_get_hl_by_name\", [highlight, 1]]\n        })\n\n        const [highlightInfo] = await this.request<[IVimHighlight[]]>(\"nvim_call_atomic\", [\n            atomicCalls,\n        ])\n\n        const ret = highlightInfo.reduce(\n            (prev: TokenColor[], currentValue: IVimHighlight, currentIndex: number) => {\n                const highlightGroupName = vimHighlights[currentIndex]\n                const settings = vimHighlightToTokenColorStyle(currentValue)\n                const newScopeNames: string[] = VimHighlightToDefaultScope[highlightGroupName] || []\n\n                const newScopes = newScopeNames.map(scope => ({\n                    scope: [scope],\n                    settings,\n                }))\n\n                return [...prev, ...newScopes]\n            },\n            [] as TokenColor[],\n        )\n\n        return ret\n    }\n\n    public setFont(\n        fontFamily: string,\n        fontSize: string,\n        fontWeight: string,\n        linePadding: number,\n    ): void {\n        this._fontFamily = fontFamily\n        this._fontSize = fontSize\n        this._fontWeight = fontWeight\n\n        const { width, height, isBoldAvailable, isItalicAvailable } = measureFont(\n            this._fontFamily,\n            this._fontSize,\n            this._fontWeight,\n        )\n\n        this._fontWidthInPixels = width\n        this._fontHeightInPixels = height + linePadding\n\n        this.emit(\n            \"action\",\n            Actions.setFont({\n                fontFamily,\n                fontSize,\n                fontWeight,\n                fontWidthInPixels: width,\n                fontHeightInPixels: height + linePadding,\n                linePaddingInPixels: linePadding,\n                isItalicAvailable,\n                isBoldAvailable,\n            }),\n        )\n\n        this.resize(this._lastWidthInPixels, this._lastHeightInPixels)\n    }\n\n    public open(fileName: string): Promise<void> {\n        return this.command(`e! ${fileName}`)\n    }\n\n    /**\n     * closeAllBuffers\n     *\n     * silently close all open buffers\n     */\n    public async closeAllBuffers() {\n        await this.command(`silent! %bdelete`)\n    }\n\n    /**\n     * getInitVimPath\n     * return the init vim path with no check to ensure existence\n     */\n    public getInitVimPath(): string {\n        // tslint:disable no-string-literal\n        const MYVIMRC = process.env[\"MYVIMRC\"]\n        const rootFolder = Platform.isWindows()\n            ? // Use path from: https://github.com/neovim/neovim/wiki/FAQ\n              path.join(process.env[\"LOCALAPPDATA\"], \"nvim\")\n            : path.join(Platform.getUserHome(), \".config\", \"nvim\")\n        const initVimPath = MYVIMRC || path.join(rootFolder, \"init.vim\")\n        return initVimPath\n        // tslint:enable no-string-literal\n    }\n\n    /**\n     * doesInitVimExist\n     * Returns the init.vim path after checking the file exists\n     */\n    public doesInitVimExist(): string {\n        const initVimPath = this.getInitVimPath()\n        try {\n            return pathExistsSync(initVimPath) ? initVimPath : null\n        } catch (e) {\n            return null\n        }\n    }\n\n    public openInitVim(): Promise<void> {\n        const loadInitVim = this._configuration.getValue(\"oni.loadInitVim\")\n\n        if (typeof loadInitVim === \"string\") {\n            return this.open(loadInitVim)\n        } else {\n            const initVimPath = this.getInitVimPath()\n            const rootFolder = path.dirname(initVimPath)\n            mkdirp.sync(rootFolder)\n\n            return this.open(initVimPath)\n        }\n    }\n\n    public eval<T>(expression: string): Promise<T> {\n        return this.request(\"nvim_eval\", [expression])\n    }\n\n    public command(command: string): Promise<any> {\n        Log.verbose(\"[NeovimInstance] Executing command: \" + command)\n        return this.request<any>(\"nvim_command\", [command])\n    }\n\n    public callFunction(functionName: string, args: any[]): Promise<any> {\n        return this.request<void>(\"nvim_call_function\", [functionName, args])\n    }\n\n    public async getBufferIds(): Promise<number[]> {\n        const buffers = await this.request<NeovimBufferReference[]>(\"nvim_list_bufs\", [])\n\n        return buffers.map(b => b.id as any)\n    }\n\n    public async getCurrentWorkingDirectory(): Promise<string> {\n        const currentWorkingDirectory = await this.eval<string>(\"getcwd()\")\n        return path.normalize(currentWorkingDirectory)\n    }\n\n    public get cursorPosition(): IPosition {\n        return {\n            row: 0,\n            column: 0,\n        }\n    }\n\n    public screenToPixels(_row: number, _col: number): IPixelPosition {\n        return {\n            x: 0,\n            y: 0,\n        }\n    }\n\n    public input(inputString: string): Promise<void> {\n        return this._inputQueue.enqueuePromise(async () => {\n            await this._neovim.request(\"nvim_input\", [inputString])\n        })\n    }\n\n    public blockInput(func: (opt?: any) => Promise<void>): void {\n        const forceInput = (inputString: string) => {\n            return this._neovim.request(\"nvim_input\", [inputString])\n        }\n\n        this._inputQueue.enqueuePromise(async () => {\n            await func(forceInput)\n        })\n    }\n\n    public resize(widthInPixels: number, heightInPixels: number): Promise<{}> {\n        this._lastWidthInPixels = widthInPixels\n        this._lastHeightInPixels = heightInPixels\n\n        const size = this._getSize()\n\n        return this._resizeInternal(size.rows, size.cols)\n    }\n\n    public async getApiVersion(): Promise<INeovimApiVersion> {\n        const versionInfo = await this._neovim.request(\"nvim_get_api_info\", [])\n        return versionInfo[1].version as any\n    }\n\n    public async quit(): Promise<void> {\n        // This command won't resolve the promise (since it's quitting),\n        // so we're not awaiting..\n        // TODO: Is there a way we can deterministically resolve the promise? Like use the `VimLeave` event?\n        this.command(\":qa!\")\n    }\n\n    private async _checkAndFixIfBlocked(): Promise<void> {\n        Log.info(\"[NeovimInstance::_checkAndFixIfBlocked] checking mode...\")\n        const mode: any = await this._neovim.request(\"nvim_get_mode\", [])\n\n        if (mode && mode.blocking) {\n            Log.info(\"[NeovimInstance::_checkAndFixIfBlocked] mode is blocking, attempt to cancel.\")\n            // The UI is blocked on some error message.\n            // Let's grab the message and show it, and unblock the UI\n            await this.input(\"<esc>\")\n            const output = await this._neovim.request<string>(\"nvim_command_output\", [\":messages\"])\n            Log.info(\"[NeovimInstance::_checkAndFixIfBlocked] sent esc, getting command\")\n\n            this._onMessage.dispatch({\n                severity: \"error\",\n                title: \"Problem loading `init.vim`:\",\n                details: output,\n            })\n        } else {\n            Log.info(\"[NeovimInstance::_checkAndFixIfBlocked] Not blocking mode.\")\n        }\n    }\n\n    private _dispatchScrollEvent(): void {\n        if (this._pendingScrollTimeout || this._isDisposed) {\n            return\n        }\n\n        this._pendingScrollTimeout = window.setTimeout(async () => {\n            if (this._isDisposed) {\n                return\n            }\n\n            const evt = await this.getContext()\n            this._onScroll.dispatch(evt)\n            this._pendingScrollTimeout = null\n        })\n    }\n\n    private _resizeInternal(rows: number, columns: number): Promise<{}> {\n        if (this._configuration.hasValue(\"debug.fixedSize\")) {\n            const fixedSize = this._configuration.getValue(\"debug.fixedSize\")\n            rows = fixedSize.rows\n            columns = fixedSize.columns\n            Log.warn(\"Overriding screen size based on debug.fixedSize\")\n        }\n\n        if (rows === this._rows && columns === this._cols) {\n            return Promise.resolve({})\n        }\n\n        this._rows = rows\n        this._cols = columns\n\n        // If _initPromise isn't initialized, it means the UI hasn't attached to NeoVim\n        // yet. In that case, we don't need to call uiTryResize\n        if (!this._initPromise) {\n            return Promise.resolve({})\n        }\n\n        return this._initPromise.then(() => {\n            return this._neovim.request(\"nvim_ui_try_resize\", [columns, rows])\n        })\n    }\n\n    private _getSize() {\n        const rows = Math.floor(this._lastHeightInPixels / this._fontHeightInPixels)\n        const cols = Math.floor(this._lastWidthInPixels / this._fontWidthInPixels)\n        return { rows, cols }\n    }\n\n    private _handleNotification(_method: any, args: any): void {\n        if (this._isDisposed) {\n            Log.warn(`[NeovimInstance] - ignoring ${_method} because disposed`)\n            return\n        }\n\n        args.forEach((a: any[]) => {\n            const command = a[0]\n            a = a.slice(1)\n\n            switch (command) {\n                case \"cursor_goto\":\n                    this.emit(\"action\", Actions.createCursorGotoAction(a[0][0], a[0][1]))\n                    break\n                case \"put\":\n                    const charactersToPut = a.map(v => v[0])\n                    this.emit(\"action\", Actions.put(charactersToPut))\n                    break\n                case \"set_scroll_region\":\n                    const param = a[0]\n                    this.emit(\n                        \"action\",\n                        Actions.setScrollRegion(param[0], param[1], param[2], param[3]),\n                    )\n                    break\n                case \"scroll\":\n                    this.emit(\"action\", Actions.scroll(a[0][0]))\n                    this._dispatchScrollEvent()\n                    break\n                case \"highlight_set\":\n                    const highlightInfo = a[a.length - 1][0]\n\n                    this.emit(\n                        \"action\",\n                        Actions.setHighlight(\n                            !!highlightInfo.bold,\n                            !!highlightInfo.italic,\n                            !!highlightInfo.reverse,\n                            !!highlightInfo.underline,\n                            !!highlightInfo.undercurl,\n                            highlightInfo.foreground,\n                            highlightInfo.background,\n                            highlightInfo.special,\n                        ),\n                    )\n                    break\n                case \"resize\":\n                    this.emit(\"action\", Actions.resize(a[0][0], a[0][1]))\n                    break\n                case \"set_title\":\n                    this._onTitleChanged.dispatch(a[0][0])\n                    break\n                case \"set_icon\":\n                    // window title when minimized, no-op\n                    break\n                case \"eol_clear\":\n                    this.emit(\"action\", Actions.clearToEndOfLine())\n                    break\n                case \"clear\":\n                    this.emit(\"action\", Actions.clear())\n                    break\n                case \"mouse_on\":\n                    // TODO\n                    break\n                case \"update_bg\":\n                    this.emit(\"action\", Actions.updateBackground(a[0][0]))\n                    break\n                case \"update_fg\":\n                    this.emit(\"action\", Actions.updateForeground(a[0][0]))\n                    break\n                case \"mode_change\":\n                    const newMode = a[a.length - 1][0]\n                    this.emit(\"action\", Actions.changeMode(newMode))\n                    this._onModeChanged.dispatch(newMode as Oni.Vim.Mode)\n                    break\n                case \"popupmenu_select\":\n                    this._onSelectPopupMenu.dispatch(a[0][0])\n                    break\n                case \"popupmenu_hide\":\n                    this._onHidePopupMenu.dispatch()\n                    break\n                case \"popupmenu_show\":\n                    const [items, selected, row, col] = a[0]\n\n                    const mappedItems = items.map((item: string[]) => {\n                        const [word, kind, menu, info] = item\n                        return {\n                            word,\n                            kind,\n                            menu,\n                            info,\n                        }\n                    })\n\n                    const completionInfo: INeovimCompletionInfo = {\n                        items: mappedItems,\n                        selectedIndex: selected,\n                        row,\n                        col,\n                    }\n\n                    this._onShowPopupMenu.dispatch(completionInfo)\n                    break\n                case \"tabline_update\":\n                    const [currentTab, tabs] = a[0]\n                    const mappedTabs: any = tabs.map((t: any) => ({\n                        id: t.tab.id,\n                        name: t.name,\n                    }))\n                    this.emit(\"tabline-update\", currentTab.id, mappedTabs)\n                    break\n                case \"bell\":\n                    const bellUrl = this._configuration.getValue(\"oni.audio.bellUrl\")\n                    if (bellUrl) {\n                        const audio = new Audio(bellUrl)\n                        audio.play()\n                    }\n                    break\n                case \"cmdline_show\":\n                    {\n                        const [content, pos, firstc, prompt, indent, level] = a[0]\n                        const commandLineShowInfo: INeovimCommandLineShowEvent = {\n                            content,\n                            pos,\n                            firstc,\n                            prompt,\n                            indent,\n                            level,\n                        }\n                        this._onCommandLineShowEvent.dispatch(commandLineShowInfo)\n                    }\n                    break\n                case \"cmdline_pos\":\n                    {\n                        const [pos, level] = a[0]\n                        const commandLinePositionInfo: INeovimCommandLineSetCursorPosition = {\n                            pos,\n                            level,\n                        }\n                        this._onCommandLineSetCursorPositionEvent.dispatch(commandLinePositionInfo)\n                    }\n                    break\n                case \"cmdline_hide\":\n                    this._onCommandLineHideEvent.dispatch()\n                    break\n                case \"wildmenu_show\":\n                    const [[options]] = a\n                    this._onWildMenuShowEvent.dispatch({ options })\n                    break\n                case \"wildmenu_select\":\n                    const [[selection]] = a\n                    this._onWildMenuSelectEvent.dispatch({ selected: selection })\n                    break\n                case \"wildmenu_hide\":\n                    this._onWildMenuHideEvent.dispatch()\n                    break\n                case \"update_sp\":\n                case \"mode_info_set\":\n                case \"busy_start\":\n                case \"busy_stop\":\n                    Log.verbose(\"Ignore command: \" + command)\n                    break\n                default:\n                    Log.warn(\"Unhandled command: \" + command)\n            }\n        })\n    }\n\n    private _onError(error: Error | string): void {\n        Log.error(error)\n        this._onErrorEvent.dispatch(error)\n    }\n\n    private _onNotification(method: string, args: any): void {\n        if (method === \"redraw\") {\n            this._handleNotification(method, args)\n            this._onRedrawComplete.dispatch()\n        } else if (method === \"oni_plugin_notify\") {\n            const pluginArgs = args[0]\n            const pluginMethod = pluginArgs.shift()\n\n            // TODO: Update pluginManager to subscribe from event here, instead of dupliating this\n\n            if (pluginMethod === \"buffer_update\") {\n                const eventContext: EventContext = args[0][0]\n\n                this._bufferUpdateManager.notifyFullBufferUpdate(eventContext)\n            } else if (pluginMethod === \"oni_yank\") {\n                this._onYank.dispatch(args[0][0])\n            } else if (pluginMethod === \"oni_command\") {\n                this._onOniCommand.dispatch(args[0][0])\n            } else if (pluginMethod === \"event\") {\n                const eventName = args[0][0]\n                const eventContext = args[0][1]\n\n                if (eventName === \"DirChanged\") {\n                    this._updateProcessDirectory()\n                } else if (eventName === \"VimLeave\") {\n                    this._isLeaving = true\n                    this._onLeave.dispatch()\n                } else if (eventName === \"ColorScheme\") {\n                    this._onColorsChanged.dispatch()\n                }\n\n                this._autoCommands.notifyAutocommand(eventName, eventContext)\n\n                this._dispatchEvent(eventName, eventContext)\n            } else if (pluginMethod === \"incremental_buffer_update\") {\n                const eventContext = args[0][0]\n                const lineContents = args[0][1]\n                const lineNumber = args[0][2]\n\n                this._bufferUpdateManager.notifyIncrementalBufferUpdate(\n                    eventContext,\n                    lineNumber,\n                    lineContents,\n                )\n            } else {\n                Log.warn(\"Unknown event from oni_plugin_notify: \" + pluginMethod)\n            }\n        } else {\n            Log.warn(\"Unknown notification: \" + method)\n        }\n    }\n\n    private _dispatchEvent(eventName: string, context: any): void {\n        const eventContext: EventContext = context.current || context\n        this._onVimEvent.dispatch({\n            eventName,\n            eventContext,\n        })\n\n        // TODO: Remove this\n        this.emit(\"event\", eventName, eventContext)\n    }\n\n    private async _updateProcessDirectory(): Promise<void> {\n        this._currentVimDirectory = await this.getCurrentWorkingDirectory()\n        this._onDirectoryChanged.dispatch(this._currentVimDirectory)\n    }\n\n    private async _attachUI(columns: number, rows: number): Promise<void> {\n        const version = await this.getApiVersion()\n\n        const useNativeTabs = this._configuration.getValue(\"tabs.mode\") === \"native\"\n        const useNativePopupWindows =\n            this._configuration.getValue(\"editor.completions.mode\") === \"native\"\n\n        const externaliseTabline = !useNativeTabs\n        const externalisePopupWindows = !useNativePopupWindows\n\n        Log.info(\n            `[NeovimInstance::_attachUI] Neovim version reported as ${version.major}.${\n                version.minor\n            }.${version.patch}`,\n        ) // tslint:disable-line no-console\n\n        const startupOptions = this._getStartupOptionsForVersion(\n            version.major,\n            version.minor,\n            version.patch,\n            externaliseTabline,\n            externalisePopupWindows,\n        )\n\n        Log.info(\n            `[NeovimInstance::_attachUI] Using startup options: ${JSON.stringify(\n                startupOptions,\n            )} and size: ${columns}, ${rows}`,\n        )\n\n        await this._neovim.request(\"nvim_ui_attach\", [columns, rows, startupOptions])\n    }\n\n    private _getStartupOptionsForVersion(\n        major: number,\n        minor: number,\n        patch: number,\n        shouldExtTabs: boolean,\n        shouldExtPopups: boolean,\n    ) {\n        if (major > 0 || minor > 2 || (minor === 2 && patch >= 1)) {\n            const useExtCmdLine = this._configuration.getValue(\"commandline.mode\")\n            const useExtWildMenu = this._configuration.getValue(\"wildmenu.mode\")\n            return {\n                rgb: true,\n                popupmenu_external: shouldExtPopups,\n                ext_tabline: shouldExtTabs,\n                ext_cmdline: useExtCmdLine,\n                ext_wildmenu: useExtWildMenu,\n            }\n        } else if (major === 0 && minor === 2) {\n            // 0.1 and below does not support external tabline\n            // See #579 for more info on the manifestation.\n            return {\n                rgb: true,\n                popupmenu_external: shouldExtPopups,\n            }\n        } else {\n            throw new Error(\"Unsupported version of Neovim.\")\n        }\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/NeovimMarks.ts",
    "content": "/**\n * NeovimMarks.ts\n *\n * Strongly typed interface to Neovim's mark functionality\n */\n\nimport { Event, IEvent } from \"oni-types\"\n\nimport { NeovimInstance } from \"./NeovimInstance\"\n\nexport interface INeovimMarkInfo {\n    mark: string\n    global: boolean\n    line: number\n    column: number\n    text: string\n}\n\nexport interface INeovimMarks {\n    onMarksUpdated: IEvent<INeovimMarkInfo[]>\n\n    /**\n     * Call to start watching marks. Note that this forces\n     * the mappings to the canonical `ma`, etc.\n     */\n    watchMarks(): void\n}\n\nconst parseMarks = (marks: string): INeovimMarkInfo[] => {\n    if (!marks) {\n        return []\n    }\n\n    const allLines = marks.split(\"\\n\")\n\n    // First two lines are a new line and the headers -\n    // we don't care about those.\n    const [, , ...markLines] = allLines\n\n    const ret = markLines.map(ml => parseMarkLine(ml))\n\n    return ret\n}\n\nconst isWhitespace = (character: string): boolean => /\\s/.test(character)\nconst isAlphaNumeric = (character: string): boolean => /^[a-z0-9]+$/i.test(character)\n\nconst getNextNonWhitespaceCharacter = (str: string, start: number): number => {\n    let idx = start\n    while (idx < str.length) {\n        if (!isWhitespace(str[idx])) {\n            return idx\n        }\n        idx++\n    }\n\n    return -1\n}\n\nconst getNextWhitespaceCharacter = (str: string, start: number): number => {\n    let idx = start\n    while (idx < str.length) {\n        if (isWhitespace(str[idx])) {\n            return idx\n        }\n        idx++\n    }\n\n    return -1\n}\n\nconst isLowerCase = (str: string) => str.toLowerCase() === str\n\nexport const parseMarkLine = (markLine: string): INeovimMarkInfo => {\n    const markStartIndex = getNextNonWhitespaceCharacter(markLine, 0)\n    const markEndIndex = getNextWhitespaceCharacter(markLine, markStartIndex + 1)\n\n    const lineStartIndex = getNextNonWhitespaceCharacter(markLine, markEndIndex + 1)\n    const lineEndIndex = getNextWhitespaceCharacter(markLine, lineStartIndex + 1)\n\n    const columnStartIndex = getNextNonWhitespaceCharacter(markLine, lineEndIndex + 1)\n    const columnEndIndex = getNextWhitespaceCharacter(markLine, columnStartIndex + 1)\n\n    const textStartIndex = getNextNonWhitespaceCharacter(markLine, columnEndIndex + 1)\n\n    const mark = markLine.substring(markStartIndex, markEndIndex)\n    const lineNumber = parseInt(markLine.substring(lineStartIndex, lineEndIndex), 10)\n    const column = parseInt(markLine.substring(columnStartIndex, columnEndIndex), 10)\n    const text = markLine.substring(textStartIndex, markLine.length)\n    const isGlobal = !isLowerCase(mark)\n\n    return {\n        mark,\n        line: lineNumber,\n        column,\n        text,\n        global: isGlobal,\n    }\n}\n\nexport class NeovimMarks {\n    private _onMarksUpdatedEvent = new Event<INeovimMarkInfo[]>()\n    private _isWatching: boolean = false\n\n    public get onMarksUpdated(): IEvent<INeovimMarkInfo[]> {\n        return this._onMarksUpdatedEvent\n    }\n\n    constructor(private _neovimInstance: NeovimInstance) {}\n\n    public watchMarks(): void {\n        if (this._isWatching) {\n            return\n        }\n        this._isWatching = true\n        this._neovimInstance.callFunction(\"OniListenForMarks\", [])\n\n        this._neovimInstance.onOniCommand.subscribe(context => {\n            if (context.command === \"_internal.notifyMarksChanged\") {\n                this._updateMarks()\n            }\n        })\n\n        this._neovimInstance.autoCommands.onBufEnter.subscribe(val => {\n            this._updateMarks()\n        })\n    }\n\n    private async _updateMarks(): Promise<void> {\n        const latestMarks = await this._readMarks()\n        this._onMarksUpdatedEvent.dispatch(latestMarks)\n    }\n\n    private async _readMarks(): Promise<INeovimMarkInfo[]> {\n        const markInfo: string = await this._neovimInstance.request<string>(\"nvim_command_output\", [\n            \":marks\",\n        ])\n\n        const allMarks = parseMarks(markInfo)\n\n        // We'll only show the alpha-numeric marks, because those are\n        // the only ones we're tracking updates on.\n\n        const marks = allMarks.filter(am => isAlphaNumeric(am.mark))\n        return marks\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/NeovimProcessSpawner.ts",
    "content": "import { ChildProcess } from \"child_process\"\nimport * as net from \"net\"\nimport * as path from \"path\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport * as Platform from \"./../Platform\"\nimport Process from \"./../Plugins/Api/Process\"\n\nimport { Session } from \"./Session\"\n\n// Most of the paths coming in the packaged binary reference the `app.asar`,\n// but the binaries (Neovim) as well as the .vim files are unpacked,\n// so these need to be mapped to the `app.asar.unpacked` directory\nconst remapPathToUnpackedAsar = (originalPath: string) => {\n    return originalPath.split(\"app.asar\").join(\"app.asar.unpacked\")\n}\n\nexport type MsgPackTransport = \"stdio\" | \"pipe\"\n\nexport interface INeovimStartOptions {\n    runtimePaths?: string[]\n    transport?: MsgPackTransport\n\n    // If `true`, load init.vim from default path\n    // If a string, override and load init.vim from the specified path\n    loadInitVim: boolean | string\n\n    // Whether or not to use Oni's default, opinionated plugins\n    useDefaultConfig: boolean\n\n    // Explicitly specify the path to Neovim. If not specified,\n    // the default path will be used.\n    neovimPath?: string\n}\n\nconst DefaultStartOptions: INeovimStartOptions = {\n    runtimePaths: [],\n    transport: \"stdio\",\n    loadInitVim: true,\n    useDefaultConfig: true,\n}\n\nconst getSessionFromProcess = async (\n    neovimProcess: ChildProcess,\n    transport: MsgPackTransport = \"stdio\",\n): Promise<Session> => {\n    Log.info(\"Initializing neovim process using transport: \" + transport)\n\n    const stdioSession = new Session(neovimProcess.stdin, neovimProcess.stdout)\n\n    if (transport === \"stdio\") {\n        return stdioSession\n    }\n\n    const namedPipe = await stdioSession.request<string>(\"nvim_eval\", [\"v:servername\"])\n\n    const client = net.createConnection(namedPipe, () => {\n        Log.info(\"NeovimProcess - connected via named pipe: \" + namedPipe)\n    })\n\n    return new Session(client, client)\n}\n\nexport const startNeovim = async (\n    options: INeovimStartOptions = DefaultStartOptions,\n): Promise<Session> => {\n    const runtimePaths = options.runtimePaths || []\n\n    const noopInitVimPath = remapPathToUnpackedAsar(path.join(__dirname, \"vim\", \"noop.vim\"))\n\n    const nvimWindowsProcessPath =\n        process.env.ONI_NEOVIM_PATH ||\n        path.join(\n            __dirname,\n            \"node_modules\",\n            \"oni-neovim-binaries\",\n            \"bin\",\n            \"Neovim\",\n            \"bin\",\n            \"nvim.exe\",\n        )\n\n    const nvimMacProcessPath =\n        process.env.ONI_NEOVIM_PATH ||\n        path.join(\n            __dirname,\n            \"node_modules\",\n            \"oni-neovim-binaries\",\n            \"bin\",\n            \"nvim-osx64\",\n            \"bin\",\n            \"nvim\",\n        )\n\n    // Assume nvim is available in path for Linux\n    const nvimLinuxPath = process.env.ONI_NEOVIM_PATH || \"nvim\"\n\n    let nvimProcessPath = Platform.isWindows()\n        ? nvimWindowsProcessPath\n        : Platform.isMac()\n            ? nvimMacProcessPath\n            : nvimLinuxPath\n\n    nvimProcessPath = remapPathToUnpackedAsar(nvimProcessPath)\n\n    if (options.neovimPath) {\n        nvimProcessPath = options.neovimPath\n    }\n\n    Log.info(\"[NeovimProcessSpawner::startNeovim] Neovim process path: \" + nvimProcessPath)\n\n    const joinedRuntimePaths = runtimePaths.map(p => remapPathToUnpackedAsar(p)).join(\",\")\n\n    const loadInitVimConfigOption = options.loadInitVim\n    const useDefaultConfig = options.useDefaultConfig\n\n    let initVimArg = []\n    initVimArg = loadInitVimConfigOption || !useDefaultConfig ? [] : [\"-u\", noopInitVimPath]\n\n    if (typeof loadInitVimConfigOption === \"string\") {\n        initVimArg = [\"-u\", loadInitVimConfigOption]\n    }\n\n    const argsToPass = initVimArg.concat([\n        \"--cmd\",\n        `let &rtp.=',${joinedRuntimePaths}'`,\n        \"--cmd\",\n        \"let g:gui_oni = 1\",\n        \"-N\",\n        \"--embed\",\n        \"--\",\n    ])\n\n    Log.verbose(\n        \"[NeovimProcessSpawner::startNeovim] Sending these args to Neovim: \" +\n            argsToPass.toString(),\n    )\n    const nvimProc = await Process.spawnProcess(nvimProcessPath, argsToPass, {})\n    Log.info(`[NeovimProcessSpawner::startNeovim] Starting Neovim - process: ${nvimProc.pid}`) // tslint:disable-line no-console\n\n    return getSessionFromProcess(nvimProc, options.transport)\n}\n"
  },
  {
    "path": "browser/src/neovim/NeovimTokenColorSynchronizer.ts",
    "content": "/**\n * NeovimTokenColorSynchronizer\n *\n * This is a helper that pushes all the token colors to Neovim\n * as custom highlight groups.\n */\n\nimport * as Color from \"color\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { TokenColor } from \"./../Services/TokenColors\"\n\nimport { NeovimInstance } from \"./NeovimInstance\"\n\nconst getGuiStringFromTokenColor = ({ settings: { fontStyle } }: TokenColor): string => {\n    if (!fontStyle) {\n        return \"gui=none\"\n    } else if (fontStyle.includes(\"bold italic\")) {\n        return \"gui=bold,italic\"\n    } else if (fontStyle === \"bold\") {\n        return \"gui=bold\"\n    } else if (fontStyle === \"italic\") {\n        return \"gui=italic\"\n    } else {\n        return \"gui=none\"\n    }\n}\n\nexport class NeovimTokenColorSynchronizer {\n    private _currentIndex = 0\n    private _tokenScopeSelectorToHighlightName: { [key: string]: string } = {}\n    private _highlightNameToHighlightValue = new Map<string, string>()\n\n    constructor(private _neovimInstance: NeovimInstance) {\n        this._neovimInstance.onColorsChanged.subscribe(this._resetHighlightCache)\n    }\n\n    // This method creates highlight groups for any token colors that haven't been set yet\n    public async synchronizeTokenColors(tokenColors: TokenColor[]) {\n        const highlightsToAdd = tokenColors.reduce<string[]>((newHighlights, tokenColor) => {\n            const highlightName = this._getOrCreateHighlightGroup(tokenColor)\n            const highlightFromScope = this._convertTokenStyleToHighlightInfo(tokenColor)\n\n            const currentHighlight = this._highlightNameToHighlightValue.get(highlightName)\n\n            if (currentHighlight === highlightFromScope) {\n                return newHighlights\n            }\n            this._highlightNameToHighlightValue.set(highlightName, highlightFromScope)\n            return [...newHighlights, highlightFromScope]\n        }, [])\n\n        const atomicCalls = highlightsToAdd.map(hlCommand => [\"nvim_command\", [hlCommand]])\n\n        if (!atomicCalls.length) {\n            return\n        }\n\n        Log.info(\n            `[NeovimTokenColorSynchronizer::synchronizeTokenColors] Setting ${\n                atomicCalls.length\n            } highlights`,\n        )\n        this._neovimInstance.request(\"nvim_call_atomic\", [atomicCalls])\n        Log.info(\n            \"[NeovimTokenColorSynchronizer::synchronizeTokenColors] Highlights set successfully\",\n        )\n    }\n\n    /**\n     * Gets the highlight group for the particular token color. Requires that `synchronizeTokenColors` has been called\n     * previously.\n     */\n    public getHighlightGroupForTokenColor(tokenColor: TokenColor): string {\n        return this._getOrCreateHighlightGroup(tokenColor)\n    }\n\n    private _resetHighlightCache = () => {\n        this._highlightNameToHighlightValue.clear()\n    }\n\n    private _convertTokenStyleToHighlightInfo(tokenColor: TokenColor): string {\n        const name = this._getOrCreateHighlightGroup(tokenColor)\n        const foregroundColor = Color(tokenColor.settings.foreground).hex()\n        const backgroundColor = Color(tokenColor.settings.background).hex()\n        const gui = getGuiStringFromTokenColor(tokenColor)\n        return `:hi! ${name} guifg=${foregroundColor} guibg=${backgroundColor} ${gui}`\n    }\n\n    private _getOrCreateHighlightGroup(tokenColor: TokenColor): string {\n        const tokenKey = this._getKeyFromTokenColor(tokenColor)\n        const existingGroup = this._tokenScopeSelectorToHighlightName[tokenKey]\n\n        if (existingGroup) {\n            return existingGroup\n        } else {\n            this._currentIndex++\n            const newHighlightGroupName = \"oni_highlight_\" + this._currentIndex.toString()\n            Log.verbose(\n                \"[NeovimTokenColorSynchronizer::_getOrCreateHighlightGroup] Creating new highlight group - \" +\n                    newHighlightGroupName,\n            )\n            this._tokenScopeSelectorToHighlightName[tokenKey] = newHighlightGroupName\n            return newHighlightGroupName\n        }\n    }\n\n    private _getKeyFromTokenColor(tokenColor: TokenColor): string {\n        const {\n            settings: { background = \"none\", foreground = \"none\", fontStyle = \"none\" },\n        } = tokenColor\n        const separator = `__`\n        const bg = `background-${background}`\n        const fg = `foreground-${foreground}`\n        const bold = `bold-${fontStyle ? fontStyle.includes(\"bold\") : false}`\n        const italic = `italic-${fontStyle ? fontStyle.includes(\"italic\") : false}`\n        return [tokenColor.scope, bg, fg, bold, italic].join(separator)\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/NeovimWindowManager.ts",
    "content": "/**\n * NeovimWindowManager.ts\n *\n * Responsible for synchronizing the UI coordinate system / state\n * with the current state of the neovim instance.\n */\n\nimport { Observable } from \"rxjs/Observable\"\nimport { Subject } from \"rxjs/Subject\"\n\nimport \"rxjs/add/operator/distinctUntilChanged\"\n\nimport * as isEqual from \"lodash/isEqual\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { EventContext } from \"./EventContext\"\nimport { NeovimInstance } from \"./index\"\n\nimport * as Utility from \"./../Utility\"\n\ninterface NeovimWindow {\n    id: number\n}\n\nexport interface NeovimTabPageState {\n    tabId: number\n    activeWindow: NeovimActiveWindowState\n    inactiveWindows: NeovimInactiveWindowState[]\n}\n\nexport interface NeovimActiveWindowState {\n    windowNumber: number\n    bufferId: number\n    bufferFullPath: string\n\n    line: number\n    column: number\n\n    topBufferLine: number\n    bottomBufferLine: number\n\n    visibleLines: string[]\n\n    bufferToScreen: Oni.Coordinates.BufferToScreen\n    dimensions: Oni.Shapes.Rectangle\n}\n\ntype Lines = string[]\ntype Height = number\ntype Width = number\ntype WindowPosition = [number, number]\n\nexport interface NeovimInactiveWindowState {\n    windowNumber: number\n    dimensions: Oni.Shapes.Rectangle\n}\n\nexport class NeovimWindowManager extends Utility.Disposable {\n    private _scrollObservable: Subject<EventContext>\n\n    private _onWindowStateChangedEvent = new Event<NeovimTabPageState>()\n\n    public get onWindowStateChanged(): IEvent<NeovimTabPageState> {\n        return this._onWindowStateChangedEvent\n    }\n\n    constructor(private _neovimInstance: NeovimInstance) {\n        super()\n\n        this._scrollObservable = new Subject<EventContext>()\n\n        const updateScroll = (evt: EventContext) => this._scrollObservable.next(evt)\n\n        const handleCommandLineEvent = async () => {\n            const ctx = await this._neovimInstance.getContext()\n            updateScroll(ctx)\n        }\n\n        // First element of the BufEnter event is the current buffer\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufEnter.subscribe(bufs =>\n                updateScroll(bufs.current),\n            ),\n        )\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onBufWinEnter.subscribe(bufs =>\n                updateScroll(bufs.current),\n            ),\n        )\n        this.trackDisposable(\n            this._neovimInstance.onBufferUpdate.subscribe(buf => updateScroll(buf.eventContext)),\n        )\n        this.trackDisposable(this._neovimInstance.autoCommands.onWinEnter.subscribe(updateScroll))\n        this.trackDisposable(\n            this._neovimInstance.autoCommands.onCursorMoved.subscribe(updateScroll),\n        )\n        this.trackDisposable(\n            this._neovimInstance.onCommandLineShow.subscribe(handleCommandLineEvent),\n        )\n        this.trackDisposable(\n            this._neovimInstance.onCommandLineHide.subscribe(handleCommandLineEvent),\n        )\n        this.trackDisposable(this._neovimInstance.autoCommands.onVimResized.subscribe(updateScroll))\n        this.trackDisposable(this._neovimInstance.onScroll.subscribe(updateScroll))\n\n        const shouldMeasure$: Observable<void> = this._scrollObservable\n            .map((evt: EventContext) => ({\n                version: evt.version,\n                bufferTotalLines: evt.bufferTotalLines,\n                windowNumber: evt.windowNumber,\n                windowTopLine: evt.windowTopLine,\n                windowBottomLine: evt.windowBottomLine,\n                windowWidth: evt.windowWidth,\n                windowHeight: evt.windowHeight,\n            }))\n            .distinctUntilChanged(isEqual)\n\n        shouldMeasure$\n            .withLatestFrom(this._scrollObservable)\n            .switchMap(([, evt]: [any, EventContext]) =>\n                Observable.defer(() => this._remeasure(evt)),\n            )\n            .subscribe((tabState: NeovimTabPageState) => {\n                if (tabState) {\n                    this._onWindowStateChangedEvent.dispatch(tabState)\n                }\n            })\n    }\n\n    public async remeasure(): Promise<void> {\n        if (this.isDisposed) {\n            return\n        }\n\n        const newContext = await this._neovimInstance.getContext()\n        this._scrollObservable.next(newContext)\n    }\n\n    private async _remeasure(context: EventContext): Promise<NeovimTabPageState> {\n        const tabNumber = context.tabNumber\n        const allWindows = await this._neovimInstance.request<NeovimWindow[]>(\n            \"nvim_tabpage_list_wins\",\n            [tabNumber],\n        )\n\n        const activeWindow = await this._remeasureActiveWindow(context.windowNumber, context)\n\n        if (!activeWindow) {\n            return null\n        }\n\n        const inactiveWindowIds = allWindows.filter(w => w.id !== context.windowNumber)\n\n        const inactiveWindows = await Promise.all(\n            inactiveWindowIds.map(window => this._remeasureInactiveWindow(window.id)),\n        )\n\n        return {\n            tabId: tabNumber,\n            activeWindow,\n            inactiveWindows,\n        }\n    }\n\n    // The goal of this function is to acquire functions for the current window:\n    // - bufferSpaceToScreenSpace(range) => Range[]\n    // - bufferSpaceToPixelSpace(range) => Rectangle[]\n    //\n    // These are needed for rich-UI rendering (knowing where adorners and elements should be rendered,\n    // relative to text in the document). An example is the error squiggle - we need to translate the\n    // error range into pixel-range.\n    //\n    // To get those, we need some information:\n    // - The dimensions of the window itself\n    // - How each buffer line maps to the screen space\n    //\n    // We can derive these from information coming from the event handlers, along with screen width\n    private async _remeasureActiveWindow(\n        currentWinId: number,\n        context: EventContext,\n    ): Promise<NeovimActiveWindowState> {\n        const positionCalls = [\n            [\"nvim_call_function\", [\"line\", [\"w0\"]]],\n            [\"nvim_call_function\", [\"line\", [\"w$\"]]],\n        ]\n        // We query the top and bottom line positions again despite these being on the context\n        // as the values from the `BufferUpdate` event can be incorrect\n        const [[topLine, bottomLine]] = await this._neovimInstance.request<[[number, number], any]>(\n            \"nvim_call_atomic\",\n            [positionCalls],\n        )\n\n        const atomicCalls = [\n            [\"nvim_win_get_position\", [currentWinId]],\n            [\"nvim_win_get_width\", [currentWinId]],\n            [\"nvim_win_get_height\", [currentWinId]],\n            [\"nvim_buf_get_lines\", [context.bufferNumber, topLine - 1, bottomLine, false]],\n        ]\n\n        const response = await this._neovimInstance.request<\n            Array<[WindowPosition, Width, Height, Lines]>\n        >(\"nvim_call_atomic\", [atomicCalls])\n\n        if (!response) {\n            return null\n        }\n\n        const [values] = response\n\n        if (values.length === 4) {\n            // Grab the results of the `nvim_atomic_call`, as they are returned in an array\n            const [position, width, height, lines] = values\n            const [row, col] = position\n\n            // The 'gutterOffset' (difference between `wincol` and `column`) is the size of the gutter\n            // (for example, line numbers). The buffer isn't in that space, so we need to account\n            // for that.\n            const offset = context.wincol - context.column\n\n            // `contentWidth` is the number of cells the buffer is rendered itno\n            const contentWidth = width - offset\n\n            const rangesOnScreen = getBufferRanges(lines, context.windowTopLine - 1, contentWidth)\n\n            const indexWhereCursorIs = rangesOnScreen.findIndex((val: types.Range) =>\n                Utility.isInRange(context.line - 1, context.column - 1, val),\n            )\n\n            const arrayStart = indexWhereCursorIs - (context.winline - 1)\n            const arrayEnd = arrayStart + height\n\n            const ranges = rangesOnScreen.slice(arrayStart, arrayEnd)\n\n            // If there is no text in the buffer, the range will be (line, 0) -> (line, 0).\n            // This means we we wouldn't be able to map positions that don't exist yet,\n            // so we should expand out the ranges to the full content width if they are less)\n            const expandedWidthRanges = ranges.map(r => {\n                return types.Range.create(\n                    r.start.line,\n                    r.start.character,\n                    r.end.line,\n                    Math.max(r.end.character, contentWidth),\n                )\n            })\n\n            const dimensions = {\n                x: col,\n                y: row,\n                width,\n                height,\n            }\n\n            const newWindowState = {\n                windowNumber: currentWinId,\n                bufferId: context.bufferNumber,\n                bufferFullPath: context.bufferFullPath,\n                column: context.column - 1,\n                line: context.line - 1,\n                bottomBufferLine: context.windowBottomLine - 1,\n                topBufferLine: context.windowTopLine,\n                dimensions,\n                visibleLines: lines || [],\n                bufferToScreen: getBufferToScreenFromRanges(offset, expandedWidthRanges),\n            }\n\n            return newWindowState\n        } else {\n            Log.warn(\"Measure request failed\")\n            return null\n        }\n    }\n\n    /**\n     * Windows that are inactive give us less state, unfortunately - so the buffer/pixel mapping\n     * is unavailable. We should still measure the width/height/position for overlay scenarios, though\n     */\n    private async _remeasureInactiveWindow(\n        currentWinId: number,\n    ): Promise<NeovimInactiveWindowState> {\n        const atomicCalls = [\n            [\"nvim_win_get_position\", [currentWinId]],\n            [\"nvim_win_get_width\", [currentWinId]],\n            [\"nvim_win_get_height\", [currentWinId]],\n        ]\n\n        const response = await this._neovimInstance.request(\"nvim_call_atomic\", [atomicCalls])\n\n        const values = response[0]\n\n        if (values.length === 3) {\n            // Grab the results of the `nvim_atomic_call`, as they are returned in an array\n            const [position, width, height] = values\n            const [row, col] = position\n\n            const dimensions = {\n                x: col,\n                y: row,\n                width,\n                height,\n            }\n\n            const newWindowState = {\n                windowNumber: currentWinId,\n                dimensions,\n            }\n\n            return newWindowState\n        } else {\n            Log.warn(\"Measure request failed\")\n            return null\n        }\n    }\n}\n\nconst getBufferToScreenFromRanges = (gutterOffset: number, ranges: types.Range[]) => (\n    bufferPosition: types.Position,\n) => {\n    const screenLine = ranges.findIndex(v =>\n        Utility.isInRange(bufferPosition.line, bufferPosition.character, v),\n    )\n\n    if (screenLine === -1) {\n        return null\n    }\n\n    const yPos = screenLine\n    const range = ranges[screenLine]\n    const xPos = gutterOffset + bufferPosition.character - range.start.character\n\n    return {\n        screenX: xPos,\n        screenY: yPos,\n    }\n}\n\n// TODO: Need to properly handle multibyte characters here\nconst getBufferRanges = (\n    bufferLines: string[],\n    startLine: number,\n    width: number,\n): types.Range[] => {\n    let ranges: types.Range[] = []\n\n    for (let i = 0; i < bufferLines.length; i++) {\n        ranges = ranges.concat(getRangesForLine(bufferLines[i], startLine + i, width))\n    }\n\n    return ranges\n}\n\nconst getRangesForLine = (bufferLine: string, lineNumber: number, width: number): types.Range[] => {\n    if (!bufferLine || !bufferLine.length) {\n        const startPosition = types.Position.create(lineNumber, 0)\n        const endPosition = types.Position.create(lineNumber, 0)\n        return [types.Range.create(startPosition, endPosition)]\n    }\n\n    const length = bufferLine.length\n    const chunks: types.Range[] = []\n\n    for (let i = 0; i < length; i += width) {\n        const startPosition = types.Position.create(lineNumber, i)\n        const endPosition = types.Position.create(\n            lineNumber,\n            Math.min(bufferLine.length, i + width),\n        )\n        const range = types.Range.create(startPosition, endPosition)\n        chunks.push(range)\n    }\n\n    return chunks\n}\n"
  },
  {
    "path": "browser/src/neovim/QuickFix.ts",
    "content": "import { INeovimInstance } from \"./NeovimInstance\"\n\nexport type Action = \"a\" | \" \"\n\nexport interface IQuickListEntry {\n    filename: string\n    lnum: number\n    col: number\n    text: string\n}\n\nexport interface IQuickFixList {\n    setqflist(list: IQuickListEntry[], title: string, action?: Action): Promise<void>\n}\n\nexport class QuickFixList implements IQuickFixList {\n    private _neovimInstance: INeovimInstance\n\n    constructor(neovimInstance: INeovimInstance) {\n        this._neovimInstance = neovimInstance\n    }\n\n    public setqflist(list: IQuickListEntry[], title: string, action?: Action): Promise<void> {\n        action = action || \" \"\n        return this._neovimInstance.callFunction(\"setqflist\", [list, action, title])\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/Screen.ts",
    "content": "import { Grid } from \"./../Grid\"\nimport * as Actions from \"./actions\"\n\nexport type Mode = \"insert\" | \"normal\" | \"visual\" | \"cmdline_normal\"\n\nconst wcwidth = require(\"wcwidth\") // tslint:disable-line no-var-requires\n\nexport interface IHighlight {\n    bold?: boolean\n    italic?: boolean\n    reverse?: boolean\n    underline?: boolean\n    undercurl?: boolean\n\n    foregroundColor?: string\n    backgroundColor?: string\n    specialColor?: string\n\n    isItalicAvailable?: boolean\n    isBoldAvailable?: boolean\n}\n\nexport interface IScreen {\n    backgroundColor: string\n    currentBackgroundColor: string\n    currentForegroundColor: string\n    cursorColumn: number\n    cursorRow: number\n    fontFamily: null | string\n    fontHeightInPixels: number\n    fontSize: null | string\n    fontWeight: null | string\n    fontWidthInPixels: number\n    foregroundColor: string\n    height: number\n    linePaddingInPixels: number\n    mode: string\n    width: number\n    dispatch(action: Actions.IAction): void\n    getCell(x: number, y: number): ICell\n    getScrollRegion(): IScrollRegion\n}\n\nexport interface MinimalScreenForRendering {\n    backgroundColor: string\n    foregroundColor: string\n    width: number\n    height: number\n    fontFamily: string\n    fontSize: string\n    fontWeight: null | string\n    fontWidthInPixels: number\n    fontHeightInPixels: number\n    linePaddingInPixels: number\n    getCell(x: number, y: number): ICell\n}\n\nexport interface ICell {\n    character: string\n\n    /**\n     * Specify the width of the character. Some Unicode characters will take up multiple\n     * cells, like `한`, which needs to be accounted for in rendering.\n     */\n    characterWidth: number\n\n    foregroundColor?: string\n    backgroundColor?: string\n    specialColor?: string\n\n    italic?: boolean\n    bold?: boolean\n    underline?: boolean\n    undercurl?: boolean\n}\n\nexport interface IPixelPosition {\n    x: number\n    y: number\n}\n\nexport interface IPosition {\n    row: number\n    column: number\n}\n\nexport interface IScrollRegion {\n    top: number\n    bottom: number\n    left: number\n    right: number\n}\n\nconst DefaultCell: ICell = {\n    character: \"\",\n    characterWidth: 1,\n}\n\nexport class NeovimScreen implements IScreen {\n    private _backgroundColor: string = \"#000000\"\n    private _specialColor: string = \"#000000\"\n    private _currentHighlight: IHighlight = {}\n    private _cursorColumn: number = 0\n    private _cursorRow: number = 0\n    private _fontFamily: null | string = null\n    private _fontHeightInPixels: number\n    private _fontSize: null | string = null\n    private _fontWeight: null | string = null\n    private _fontWidthInPixels: number\n    private _foregroundColor: string = \"#000000\"\n    private _grid: Grid<ICell> = new Grid<ICell>()\n    private _height: number = 40\n    private _mode: Mode = \"normal\"\n    private _scrollRegion: IScrollRegion\n    private _width: number = 80\n    private _linePaddingInPixels: number\n\n    public get width(): number {\n        return this._width\n    }\n\n    public get height(): number {\n        return this._height\n    }\n\n    public get fontFamily(): null | string {\n        return this._fontFamily\n    }\n\n    public get fontSize(): null | string {\n        return this._fontSize\n    }\n\n    public get fontWeight(): null | string {\n        return this._fontWeight\n    }\n\n    public get fontWidthInPixels(): number {\n        return this._fontWidthInPixels\n    }\n\n    public get fontHeightInPixels(): number {\n        return this._fontHeightInPixels\n    }\n\n    public get linePaddingInPixels(): number {\n        return this._linePaddingInPixels\n    }\n\n    public get cursorRow(): number {\n        return this._cursorRow\n    }\n\n    public get cursorColumn(): number {\n        return this._cursorColumn\n    }\n\n    public get mode(): Mode {\n        return this._mode\n    }\n\n    public get backgroundColor(): string {\n        return this._backgroundColor\n    }\n\n    public get foregroundColor(): string {\n        return this._foregroundColor\n    }\n\n    public get specialColor(): string {\n        return this._specialColor\n    }\n\n    public get currentForegroundColor(): string {\n        return this._currentHighlight.foregroundColor || this._foregroundColor\n    }\n\n    public get currentBackgroundColor(): string {\n        return this._currentHighlight.backgroundColor || this._backgroundColor\n    }\n\n    public get currentSpecialColor(): string {\n        return this._currentHighlight.specialColor || this._specialColor\n    }\n\n    public getCell = (x: number, y: number) => {\n        const cell = this._grid.getCell(x, y)\n\n        if (cell) {\n            return cell\n        } else {\n            return DefaultCell\n        }\n    }\n\n    public dispatch(action: any): void {\n        switch (action.type) {\n            case Actions.CursorGotoType:\n                this._cursorRow = action.row\n                this._cursorColumn = action.col\n                break\n            case Actions.PutAction: {\n                let foregroundColor =\n                    this._currentHighlight.foregroundColor || this._foregroundColor\n                let backgroundColor =\n                    this._currentHighlight.backgroundColor || this._backgroundColor\n                const specialColor = this._currentHighlight.specialColor || this._specialColor\n\n                // `:help ui-event-highlight_set` specifies that the background and foreground colours\n                // are swapped if reversed is set. The special colour is not mentioned, which is why it\n                // is omitted here.\n                if (this._currentHighlight.reverse) {\n                    const temp = foregroundColor\n                    foregroundColor = backgroundColor\n                    backgroundColor = temp\n                }\n\n                const { underline, undercurl, bold, italic } = this._currentHighlight\n\n                const characters = action.characters\n                const row = this._cursorRow\n                const col = this._cursorColumn\n\n                for (let i = 0; i < characters.length; i++) {\n                    const character = characters[i]\n\n                    const characterWidth = Math.max(wcwidth(character), 1)\n\n                    this._setCell(col + i, row, {\n                        foregroundColor,\n                        backgroundColor,\n                        specialColor,\n                        character,\n                        characterWidth,\n                        italic,\n                        bold,\n                        underline,\n                        undercurl,\n                    })\n\n                    for (let c = 1; c < characterWidth; c++) {\n                        this._setCell(col + i + c, row, {\n                            foregroundColor,\n                            backgroundColor,\n                            specialColor,\n                            character: \"\",\n                            characterWidth: 0,\n                            italic,\n                            bold,\n                            underline,\n                            undercurl,\n                        })\n                    }\n\n                    i += characterWidth - 1\n                }\n\n                this._cursorColumn += characters.length\n                break\n            }\n            case Actions.CLEAR_TO_END_OF_LINE: {\n                const foregroundColor =\n                    this._currentHighlight.foregroundColor || this._foregroundColor\n                const backgroundColor =\n                    this._currentHighlight.backgroundColor || this._backgroundColor\n                const specialColor = this._currentHighlight.specialColor || this._specialColor\n\n                const row = this._cursorRow\n                for (let i = this._cursorColumn; i < this.width; i++) {\n                    this._setCell(i, row, {\n                        foregroundColor,\n                        backgroundColor,\n                        specialColor,\n                        character: \"\",\n                        characterWidth: 1,\n                        bold: this._currentHighlight.bold,\n                        italic: this._currentHighlight.italic,\n                        underline: this._currentHighlight.underline,\n                        undercurl: this._currentHighlight.undercurl,\n                    })\n                }\n                break\n            }\n            case Actions.CLEAR:\n                this._grid.clear()\n\n                this._cursorColumn = 0\n                this._cursorRow = 0\n                break\n            case Actions.RESIZE:\n                this._width = action.columns\n                this._height = action.rows\n                break\n            case Actions.SET_FONT:\n                this._fontFamily = action.fontFamily\n                this._fontSize = action.fontSize\n                this._fontWeight = action.fontWeight\n                this._fontWidthInPixels = action.fontWidthInPixels\n                this._fontHeightInPixels = action.fontHeightInPixels\n                this._linePaddingInPixels = action.linePaddingInPixels\n                this._currentHighlight.isItalicAvailable = action.isItalicAvailable\n                this._currentHighlight.isBoldAvailable = action.isBoldAvailable\n                break\n            case Actions.CHANGE_MODE:\n                this._mode = action.mode\n                break\n            case Actions.UPDATE_BG:\n                this._backgroundColor = action.color\n                break\n            case Actions.UPDATE_FG:\n                this._foregroundColor = action.color\n                break\n            case Actions.SET_HIGHLIGHT:\n                const { isBoldAvailable, isItalicAvailable } = this._currentHighlight\n                this._currentHighlight.foregroundColor = action.foregroundColor\n                this._currentHighlight.backgroundColor = action.backgroundColor\n                this._currentHighlight.specialColor = action.specialColor\n                this._currentHighlight.reverse = !!action.reverse\n                this._currentHighlight.bold = isBoldAvailable ? action.bold : false\n                this._currentHighlight.italic = isItalicAvailable ? action.italic : false\n                this._currentHighlight.undercurl = action.undercurl\n                this._currentHighlight.underline = action.underline\n                break\n            case Actions.SET_SCROLL_REGION:\n                this._scrollRegion = {\n                    top: action.top,\n                    bottom: action.bottom,\n                    left: action.left,\n                    right: action.right,\n                }\n                break\n            case Actions.SCROLL: {\n                const { top, bottom, left, right } = this.getScrollRegion()\n                const count = action.scroll\n\n                const width = right - left\n                const height = bottom - top\n                const regionToScroll = this._grid.cloneRegion(left, top, width + 1, height + 1)\n\n                regionToScroll.shiftRows(count)\n\n                this._grid.setRegionFromGrid(regionToScroll, left, top)\n                break\n            }\n            default:\n                break\n        }\n    }\n\n    public getScrollRegion(): IScrollRegion {\n        if (this._scrollRegion) {\n            return this._scrollRegion\n        } else {\n            return {\n                top: 0,\n                bottom: this.height,\n                left: 0,\n                right: this.width,\n            }\n        }\n    }\n\n    private _setCell(x: number, y: number, cell: ICell): void {\n        const currentCell = this._grid.getCell(x, y)\n        if (currentCell) {\n            if (\n                currentCell.foregroundColor === cell.foregroundColor &&\n                currentCell.backgroundColor === cell.backgroundColor &&\n                currentCell.character === cell.character\n            ) {\n                return\n            }\n        }\n\n        this._grid.setCell(x, y, cell)\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/ScreenWithPredictions.ts",
    "content": "/**\n * ScreenWithPredictions\n *\n * Wrapper over the screen that facilitates storing temporary 'typing predictions' -\n * keystrokes we get prior to be round-tripped to Neovim.\n */\n\nimport { ICell, IScreen } from \"./Screen\"\n\nimport { Configuration } from \"./../Services/Configuration\"\nimport { ITypingPrediction } from \"./../Services/TypingPredictionManager\"\n\nexport class ScreenWithPredictions {\n    private _predictedRow: number = -1\n    private _predictions: { [key: number]: ICell } = {}\n\n    constructor(private _screen: IScreen, private _configuration: Configuration) {}\n\n    public getCell = (x: number, y: number) => {\n        if (y === this._predictedRow && this._predictions[x]) {\n            return this._predictions[x]\n        }\n\n        const cell = this._screen.getCell(x, y)\n        return cell\n    }\n\n    public updatePredictions(predictions: ITypingPrediction, row: number): void {\n        this._predictedRow = row\n        this._predictions = {}\n\n        const debugHighlightingPredictions = this._configuration.getValue(\n            \"debug.showTypingPrediction\",\n        )\n        const predictionBackgroundColor = debugHighlightingPredictions\n            ? \"red\"\n            : predictions.backgroundColor\n        const predictionForegroundColor = debugHighlightingPredictions\n            ? \"white\"\n            : predictions.foregroundColor\n\n        for (let i = 0; i < predictions.predictedCharacters.length; i++) {\n            const column =\n                predictions.predictedCursorColumn - (predictions.predictedCharacters.length - i)\n\n            const cell: ICell = {\n                character: predictions.predictedCharacters[i].character,\n                characterWidth: 1,\n                backgroundColor: predictionBackgroundColor,\n                foregroundColor: predictionForegroundColor,\n            }\n\n            this._predictions[column] = cell\n        }\n    }\n\n    public get linePaddingInPixels(): number {\n        return this._screen.linePaddingInPixels\n    }\n\n    public get fontFamily(): string {\n        return this._screen.fontFamily\n    }\n\n    public get fontSize(): string {\n        return this._screen.fontSize\n    }\n\n    public get backgroundColor(): string {\n        return this._screen.backgroundColor\n    }\n\n    public get foregroundColor(): string {\n        return this._screen.foregroundColor\n    }\n\n    public get width(): number {\n        return this._screen.width\n    }\n\n    public get height(): number {\n        return this._screen.height\n    }\n\n    public get fontWidthInPixels(): number {\n        return this._screen.fontWidthInPixels\n    }\n\n    public get fontHeightInPixels(): number {\n        return this._screen.fontHeightInPixels\n    }\n\n    public get fontWeight(): string {\n        return this._screen.fontWeight\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/Session.ts",
    "content": "import * as msgpackLite from \"msgpack-lite\"\n\nimport { EventEmitter } from \"events\"\n\nimport * as Log from \"oni-core-logging\"\n\nimport { configuration } from \"./../Services/Configuration\"\n\nimport * as msgpack from \"./MsgPack\"\n\ntype RequestHandlerFunction = (result: any) => void\n\nconst log = (msg: string) => {\n    if (configuration.getValue(\"debug.detailedSessionLogging\")) {\n        Log.info(\"[DEBUG - Neovim Session] \" + msg)\n    }\n}\n\n/**\n * Session is responsible for the Neovim msgpack session\n */\nexport class Session extends EventEmitter {\n    private _isDisposed: boolean = false\n    private _encoder: msgpackLite.EncodeStream\n    private _decoder: msgpackLite.DecodeStream\n    private _requestId: number = 0\n    private _pendingRequests: { [key: number]: RequestHandlerFunction } = {}\n\n    public get isDisposed(): boolean {\n        return this._isDisposed\n    }\n\n    constructor(private _writer: NodeJS.WritableStream, private _reader: NodeJS.ReadableStream) {\n        super()\n\n        const codec = msgpackLite.createCodec()\n\n        codec.addExtPacker(0x00, msgpack.NeovimBufferReference, msgpack.Pack)\n        codec.addExtUnpacker(0x00, msgpack.UnpackBuffer)\n\n        codec.addExtPacker(0x01, msgpack.NeovimWindowReference, msgpack.Pack)\n        codec.addExtUnpacker(0x01, msgpack.UnpackWindow)\n\n        codec.addExtPacker(0x02, msgpack.NeovimTabReference, msgpack.Pack)\n        codec.addExtUnpacker(0x02, msgpack.UnpackTab)\n\n        this._encoder = msgpackLite.createEncodeStream({ codec })\n        this._decoder = msgpackLite.createDecodeStream({ codec })\n\n        this._encoder.pipe(this._writer)\n        this._reader.pipe(this._decoder)\n\n        this._decoder.on(\"data\", (data: any) => {\n            const [type, ...remaining] = data\n\n            switch (type) {\n                case 0:\n                    Log.warn(\"Unhandled request\")\n                    break\n                case 1 /* Response */:\n                    const [responseMessage, payload1, payload2] = remaining\n                    const result = payload1 || payload2\n                    log(\"Received response - \" + responseMessage + \" : \" + result)\n                    this._pendingRequests[responseMessage](result)\n                    this._pendingRequests[responseMessage] = null\n                    break\n                case 2 /* Notification */:\n                    const [notificationMessage, payload] = remaining\n                    log(\"Received notification - \" + notificationMessage)\n\n                    this.emit(\"notification\", notificationMessage, payload)\n                    break\n                default:\n                    Log.warn(\"Unhandled message\")\n            }\n        })\n\n        this._writer.on(\"error\", () => {\n            log(\"Writer error\")\n        })\n\n        this._reader.on(\"error\", () => {\n            log(\"Reader error\")\n        })\n\n        this._decoder.on(\"end\", () => {\n            log(\"Disconnect\")\n            this.emit(\"disconnect\")\n        })\n\n        this._decoder.on(\"error\", (err: Error) => {\n            if (!this._isDisposed) {\n                Log.error(\"Decoder error:\", err)\n            }\n        })\n    }\n\n    public dispose(): void {\n        this._isDisposed = true\n\n        if (this._encoder) {\n            this._encoder.end()\n            this._encoder = null\n        }\n\n        if (this._writer) {\n            this._writer.end()\n            this._writer = null\n        }\n\n        if (this._reader) {\n            this._reader = null\n        }\n\n        if (this._decoder) {\n            this._decoder.end()\n            this._decoder = null\n        }\n    }\n\n    public request<T>(methodName: string, args: any): Promise<T> {\n        if (this._isDisposed) {\n            Log.warn(`[Session] Ignoring request: ${methodName} because session is disposed.`)\n            return Promise.reject(null)\n        }\n\n        this._requestId++\n        let r = null\n        const promise = new Promise<T>((resolve, reject) => {\n            r = (val: T) => {\n                resolve(val)\n            }\n        })\n\n        if (!r) {\n            return Promise.reject(null)\n        }\n\n        log(\"Sending request - \" + methodName + \" : \" + this._requestId)\n\n        this._pendingRequests[this._requestId] = r\n        this._writeImmediate([0, this._requestId, methodName, args])\n\n        return promise\n    }\n\n    public notify(methodName: string, args: any): void {\n        if (this._isDisposed) {\n            Log.warn(`[Session] Ignoring notification: ${methodName} because session is disposed.`)\n            return\n        }\n        log(\"Sending notification - \" + methodName)\n        this._writeImmediate([2, methodName, args])\n    }\n\n    private _writeImmediate(args: any[]) {\n        // Hacks to immediately `flush` the msgpack pipeline\n        // The demo examples use `end` on the stream, but that\n        // actually closes the stream - the flush is needed\n        // to send the data immediately across the stream.\n        ;(this._encoder as any).write(args)\n        ;(this._encoder as any)._flush()\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/SharedNeovimInstance.ts",
    "content": "/**\n * SharedNeovimInstance.ts\n *\n * Specialized instance of Neovim, used as shared UX for non-traditional Vim components.\n * - Enabling Neovim keybindings on menus\n * - Enabling Neovim keybindings on trees\n * - Enabling Neovim keybindings on grids\n * - Enabling Neovim keybindings in text input elements\n */\n\nimport * as Log from \"oni-core-logging\"\nimport { Event, IDisposable, IEvent } from \"oni-types\"\n\nimport { CommandContext } from \"./CommandContext\"\nimport { NeovimInstance } from \"./NeovimInstance\"\nimport { INeovimStartOptions } from \"./NeovimProcessSpawner\"\n\nimport { PluginManager } from \"./../Plugins/PluginManager\"\nimport { commandManager } from \"./../Services/CommandManager\"\nimport { Configuration } from \"./../Services/Configuration\"\n\nimport { PromiseQueue } from \"./../Services/Language/PromiseQueue\"\n\nimport * as App from \"./../App\"\n\nexport interface IBinding {\n    input(key: string): Promise<void>\n    release(): void\n}\n\nexport interface IMenuBinding extends IBinding {\n    onCursorMoved: IEvent<string>\n\n    setItems(ids: string[], focusedId?: string): Promise<void>\n}\n\nexport class Binding implements IBinding {\n    private _onReleasedEvent: Event<void> = new Event<void>()\n    private _subscriptions: IDisposable[] = []\n\n    public get onReleased(): IEvent<void> {\n        return this._onReleasedEvent\n    }\n\n    protected get neovimInstance(): NeovimInstance {\n        return this._neovimInstance\n    }\n\n    constructor(private _neovimInstance: NeovimInstance) {}\n\n    public input(key: string): Promise<void> {\n        return this._neovimInstance.input(key)\n    }\n\n    public release(): void {\n        this._neovimInstance = null\n\n        this._subscriptions.forEach(sub => sub.dispose())\n\n        this._onReleasedEvent.dispatch()\n    }\n\n    protected trackDisposable(disposable: IDisposable): void {\n        this._subscriptions.push(disposable)\n    }\n}\n\nexport class MenuBinding extends Binding implements IMenuBinding {\n    private _currentOptions: string[] = []\n    private _currentId: string = null\n    private _onCursorMovedEvent: Event<string> = new Event<string>()\n    private _promiseQueue = new PromiseQueue()\n\n    private _isUpdating: boolean = false\n\n    public get onCursorMoved(): IEvent<string> {\n        return this._onCursorMovedEvent\n    }\n\n    constructor(neovimInstance: NeovimInstance) {\n        super(neovimInstance)\n\n        const subscription = this.neovimInstance.autoCommands.onCursorMoved.subscribe(evt => {\n            if (this._isUpdating) {\n                return\n            }\n\n            const line = evt.line - 1\n            if (line < this._currentOptions.length) {\n                this._onCursorMovedEvent.dispatch(this._currentOptions[line])\n            }\n        })\n\n        this.trackDisposable(subscription)\n    }\n\n    public async setItems(items: string[], activeId?: string): Promise<void> {\n        this._promiseQueue.enqueuePromise(async () => {\n            if (items === this._currentOptions && activeId === this._currentId) {\n                return\n            }\n\n            this._isUpdating = true\n\n            this._currentOptions = items\n            this._currentId = activeId\n\n            if (!this.neovimInstance.isInitialized) {\n                return\n            }\n            const currentWinId = await this.neovimInstance.request(\"nvim_get_current_win\", [])\n            const currentBufId = await this.neovimInstance.eval(\"bufnr('%')\")\n            const bufferLength = await this.neovimInstance.eval<number>(\"line('$')\")\n\n            const elems = []\n\n            for (let i = 0; i < this._currentOptions.length; i++) {\n                elems.push(i.toString())\n            }\n\n            let idx = 1\n            if (activeId) {\n                idx = this._currentOptions.indexOf(activeId) + 1\n            }\n\n            await this.neovimInstance.request(\"nvim_buf_set_lines\", [\n                currentBufId,\n                0,\n                bufferLength,\n                false,\n                elems,\n            ])\n            await this.neovimInstance.request(\"nvim_win_set_cursor\", [currentWinId, [idx, 1]])\n            this._isUpdating = false\n        })\n    }\n}\n\nclass SharedNeovimInstance implements SharedNeovimInstance {\n    private _neovimInstance: NeovimInstance\n    private _activeBinding: IBinding\n\n    public get isInitialized(): boolean {\n        return this._neovimInstance.isInitialized\n    }\n\n    constructor(private _configuration: Configuration, private _pluginManager: PluginManager) {\n        this._neovimInstance = new NeovimInstance(5, 5, this._configuration)\n\n        this._neovimInstance.onOniCommand.subscribe((context: CommandContext) => {\n            const commandToExecute = context.command\n            const commandArgs = context.args\n\n            commandManager.executeCommand(commandToExecute, commandArgs)\n        })\n\n        App.registerQuitHook(async () => {\n            return this.quit()\n        })\n    }\n\n    public bindToMenu(): IMenuBinding {\n        const menuBinding = new MenuBinding(this._neovimInstance)\n        this._activeBinding = menuBinding\n        return menuBinding\n    }\n\n    public async start(): Promise<void> {\n        const startOptions: INeovimStartOptions = {\n            runtimePaths: this._pluginManager.getAllRuntimePaths(),\n            loadInitVim: false,\n            useDefaultConfig: true,\n        }\n\n        Log.info(\"[SharedNeovimInstance::start] Starting...\")\n        await this._neovimInstance.start(startOptions)\n        Log.info(\"[SharedNeovimInstance::start] Started successfully!\")\n    }\n\n    public async quit(): Promise<void> {\n        if (this._activeBinding) {\n            this._activeBinding.release()\n            this._activeBinding = null\n        }\n\n        return this._neovimInstance.quit()\n    }\n}\n\nlet _sharedInstance: SharedNeovimInstance = null\nexport const activate = async (\n    configuration: Configuration,\n    pluginManager: PluginManager,\n): Promise<void> => {\n    if (_sharedInstance) {\n        return\n    }\n\n    _sharedInstance = new SharedNeovimInstance(configuration, pluginManager)\n    await _sharedInstance.start()\n}\n\nexport const getInstance = (): SharedNeovimInstance => {\n    return _sharedInstance\n}\n"
  },
  {
    "path": "browser/src/neovim/VimHighlights.ts",
    "content": "/**\n * VimHighlights\n *\n * Mapping of Vim highlight groups to default scopes\n */\n\nimport * as Color from \"color\"\n\nimport { TokenColorStyle } from \"./../Services/TokenColors\"\n\nexport interface IVimHighlight {\n    foreground: string\n    background: string\n    bold: boolean\n    italic: boolean\n}\n\nconst setFontStyle = (highlight: IVimHighlight) => {\n    switch (true) {\n        case highlight.bold && !highlight.italic:\n            return \"bold\"\n        case !highlight.bold && highlight.italic:\n            return \"italic\"\n        case highlight.bold && highlight.italic:\n            return \"bold italic\"\n        case !highlight.bold && !highlight.italic:\n        default:\n            return null\n    }\n}\n\nexport const vimHighlightToTokenColorStyle = (highlight: IVimHighlight): TokenColorStyle => {\n    return {\n        foreground: Color(highlight.foreground).hex(),\n        background: Color(highlight.background).hex(),\n        fontStyle: setFontStyle(highlight),\n    }\n}\n\nexport const VimHighlightToDefaultScope = {\n    Identifier: [\"variable.language\", \"variable.object\", \"variable.parameter\", \"variable.other\"],\n    Function: [\"support.function\", \"entity.name\"],\n    Constant: [\"variable.other.constant\", \"entity.other\"],\n    String: [\"string.quoted.double\", \"string.quoted.single\", \"string.quoted.triple\"],\n}\n"
  },
  {
    "path": "browser/src/neovim/actions.ts",
    "content": "export const CursorGotoType = \"CURSOR_GOTO_ACTION\"\nexport const PutAction = \"PUT_ACTION\"\nexport const CLEAR_TO_END_OF_LINE = \"CLEAR_TO_END_OF_LINE\"\nexport const RESIZE = \"RESIZE\"\nexport const CLEAR = \"CLEAR\"\nexport const SET_FONT = \"SET_FONT\"\nexport const CHANGE_MODE = \"CHANGE_MODE\"\nexport const UPDATE_BG = \"UPDATE_BG\"\nexport const UPDATE_FG = \"UPDATE_FG\"\nexport const UPDATE_SP = \"UPDATE_SP\"\nexport const SET_HIGHLIGHT = \"SET_HIGHLIGHT\"\n\nexport const SET_SCROLL_REGION = \"SET_SCROLL_REGION\"\nexport const SCROLL = \"SCROLL\"\n\nexport interface IAction {\n    type: string\n}\n\nexport interface ICursorGotoAction extends IAction {\n    row: number\n    col: number\n}\n\nexport interface IResizeAction extends IAction {\n    rows: number\n    columns: number\n}\n\nexport interface IPutCharacterAction extends IAction {\n    characters: string[]\n}\n\nexport interface IChangeModeAction extends IAction {\n    mode: string\n}\n\nexport interface IKeyboardInputAction extends IAction {\n    input: string\n}\n\ninterface ISetFontArguments {\n    fontFamily: string\n    fontSize: string\n    fontWeight: string\n    fontWidthInPixels: number\n    fontHeightInPixels: number\n    linePaddingInPixels: number\n    isItalicAvailable: boolean\n    isBoldAvailable: boolean\n}\n\nexport interface ISetFontAction extends IAction {\n    fontFamily: string\n    fontSize: string\n    fontWeight: string\n    fontWidthInPixels: number\n    fontHeightInPixels: number\n    linePaddingInPixels: number\n    isItalicAvailable: boolean\n    isBoldAvailable: boolean\n}\n\nexport interface IScrollAction extends IAction {\n    scroll: number\n}\n\nexport interface ISetScrollRegionAction extends IAction {\n    top: number\n    bottom: number\n    left: number\n    right: number\n}\n\nexport interface IUpdateColorAction extends IAction {\n    color: string\n}\n\nexport interface ISetHighlightAction extends IAction {\n    bold: boolean\n    italic: boolean\n    reverse: boolean\n    underline: boolean\n    undercurl: boolean\n\n    foregroundColor?: string\n    backgroundColor?: string\n    specialColor?: string\n}\n\nexport function scroll(scrollValue: number): IScrollAction {\n    return {\n        type: SCROLL,\n        scroll: scrollValue,\n    }\n}\n\nexport function setScrollRegion(\n    top: number,\n    bottom: number,\n    left: number,\n    right: number,\n): ISetScrollRegionAction {\n    return {\n        type: SET_SCROLL_REGION,\n        top,\n        bottom,\n        left,\n        right,\n    }\n}\n\nexport function setHighlight(\n    bold: boolean,\n    italic: boolean,\n    reverse: boolean,\n    underline: boolean,\n    undercurl: boolean,\n    foregroundColor?: number,\n    backgroundColor?: number,\n    specialColor?: number,\n): ISetHighlightAction {\n    const action: ISetHighlightAction = {\n        type: SET_HIGHLIGHT,\n        bold,\n        italic,\n        reverse,\n        underline,\n        undercurl,\n        foregroundColor: undefined,\n        backgroundColor: undefined,\n        specialColor: undefined,\n    }\n\n    if (foregroundColor && foregroundColor !== -1) {\n        action.foregroundColor = colorToString(foregroundColor, \"#FFFFFF\")\n    }\n\n    if (backgroundColor && backgroundColor !== -1) {\n        action.backgroundColor = colorToString(backgroundColor, \"#000000\")\n    }\n\n    if (specialColor && specialColor !== -1) {\n        action.specialColor = colorToString(specialColor, \"#000000\")\n    }\n\n    return action\n}\n\nexport const CommandLineShow = (\n    content: [any, string],\n    pos: number,\n    firstc: string,\n    prompt: string,\n    indent: number,\n    level: number,\n) => ({\n    type: \"COMMAND_LINE_SHOW\",\n    payload: {\n        content,\n        pos,\n        firstc,\n        prompt,\n        indent,\n        level,\n    },\n})\n\nfunction colorToString(color: number, defaultColor: string): string {\n    if (color === -1) {\n        return defaultColor\n    }\n\n    // tslint:disable no-bitwise\n    const r = (color >> 16) & 0xff\n    const g = (color >> 8) & 0xff\n    const b = color & 0xff\n    // tslint:enable no-bitwise\n\n    return \"#\" + _convertToHexString(r) + _convertToHexString(g) + _convertToHexString(b)\n}\n\nfunction _convertToHexString(num: number): string {\n    let hex: string = num.toString(16)\n    if (hex.length === 1) {\n        hex = \"0\" + hex\n    }\n\n    return hex\n}\n\nexport function updateBackground(color: number): IUpdateColorAction {\n    return {\n        type: UPDATE_BG,\n        color: colorToString(color, \"#000000\"),\n    }\n}\n\nexport function updateForeground(color: number): IUpdateColorAction {\n    return {\n        type: UPDATE_FG,\n        color: colorToString(color, \"#FFFFFF\"),\n    }\n}\n\nexport function changeMode(mode: string): IChangeModeAction {\n    return {\n        type: CHANGE_MODE,\n        mode,\n    }\n}\n\nexport function setFont({\n    fontFamily,\n    fontSize,\n    fontWeight,\n    fontWidthInPixels,\n    fontHeightInPixels,\n    linePaddingInPixels,\n    isItalicAvailable,\n    isBoldAvailable,\n}: ISetFontArguments): ISetFontAction {\n    return {\n        type: SET_FONT,\n        fontFamily,\n        fontSize,\n        fontWeight,\n        fontWidthInPixels,\n        fontHeightInPixels,\n        linePaddingInPixels,\n        isItalicAvailable,\n        isBoldAvailable,\n    }\n}\n\nexport function clear(): IAction {\n    return {\n        type: CLEAR,\n    }\n}\n\nexport function resize(columns: number, rows: number): IResizeAction {\n    return {\n        type: RESIZE,\n        rows,\n        columns,\n    }\n}\n\nexport function put(characters: string[]): IPutCharacterAction {\n    return {\n        type: PutAction,\n        characters,\n    }\n}\n\nexport function clearToEndOfLine(): IAction {\n    return {\n        type: CLEAR_TO_END_OF_LINE,\n    }\n}\n\nexport function createKeyboardInputAction(key: string): IKeyboardInputAction {\n    return {\n        type: \"KeyboardInputAction\",\n        input: key,\n    }\n}\n\nexport function createCursorGotoAction(row: number, col: number): ICursorGotoAction {\n    return {\n        type: CursorGotoType,\n        row,\n        col,\n    }\n}\n\nexport const createStartNeovimAction = () => {\n    return {\n        type: \"StartNeovimAction\",\n    }\n}\n\nexport const createKeyboardInitializeAction = () => {\n    return {\n        type: \"KeyboardInitialize\",\n    }\n}\n"
  },
  {
    "path": "browser/src/neovim/index.ts",
    "content": "export * from \"./actions\"\nexport * from \"./EventContext\"\nexport * from \"./MsgPack\"\nexport * from \"./Screen\"\nexport * from \"./ScreenWithPredictions\"\nexport * from \"./Session\"\nexport * from \"./NeovimProcessSpawner\"\nexport * from \"./NeovimInstance\"\nexport * from \"./NeovimMarks\"\nexport * from \"./NeovimWindowManager\"\nexport * from \"./QuickFix\"\n"
  },
  {
    "path": "browser/src/neovim-client.d.ts",
    "content": "declare module \"neovim-client\" {\n    export default attach\n    function attach(\n        writer: NodeJS.WritableStream,\n        reader: NodeJS.ReadableStream,\n        cb: (err: Error, nvim: INvim) => void,\n    )\n\n    interface INvim {\n        uiAttach(\n            width: number,\n            height: boolean,\n            enableRgb: (err: Error) => void,\n            cb: (err: Error) => void,\n        ): void\n        uiDetach(cb: (err: Error) => void): void\n        uiTryResize(\n            width: number,\n            height: (err: Error, res: Object) => void,\n            cb: (err: Error, res: Object) => void,\n        ): void\n        command(str: string, cb: (err: Error) => void): void\n        feedkeys(keys: string, mode: string, escapeCsi: boolean, cb: (err: Error) => void): void\n        input(keys: string, cb: (err: Error, res: number) => void): void\n        replaceTermcodes(\n            str: string,\n            fromPart: boolean,\n            doLt: boolean,\n            special: boolean,\n            cb: (err: Error, res: string) => void,\n        ): void\n        commandOutput(str: string, cb: (err: Error, res: string) => void): void\n        eval(str: string, cb: (err: Error, res: Object) => void): void\n        callFunction(fname: string, args: any[], cb: (err: Error, res: Object) => void): void\n        strwidth(str: string, cb: (err: Error, res: number) => void): void\n        listRuntimePaths(cb: (err: Error, res: string[]) => void): void\n        changeDirectory(dir: string, cb: (err: Error) => void): void\n        getCurrentLine(cb: (err: Error, res: string) => void): void\n        setCurrentLine(line: string, cb: (err: Error) => void): void\n        delCurrentLine(cb: (err: Error) => void): void\n        getVar(name: string, cb: (err: Error, res: Object) => void): void\n        setVar(name: string, value: Object, cb: (err: Error, res: Object) => void): void\n        delVar(name: string, cb: (err: Error, res: Object) => void): void\n        getVvar(name: string, cb: (err: Error, res: Object) => void): void\n        getOption(name: string, cb: (err: Error, res: Object) => void): void\n        setOption(name: string, value: Object, cb: (err: Error) => void): void\n        outWrite(str: string, cb: (err: Error) => void): void\n        errWrite(str: string, cb: (err: Error) => void): void\n        reportError(str: string, cb: (err: Error) => void): void\n        getBuffers(cb: (err: Error, res: IBuffer[]) => void): void\n        getCurrentBuffer(cb: (err: Error, res: IBuffer) => void): void\n        setCurrentBuffer(buffer: IBuffer, cb: (err: Error) => void): void\n        getWindows(cb: (err: Error, res: IWindow[]) => void): void\n        getCurrentWindow(cb: (err: Error, res: IWindow) => void): void\n        setCurrentWindow(window: IWindow, cb: (err: Error) => void): void\n        getTabpages(cb: (err: Error, res: ITabpage[]) => void): void\n        getCurrentTabpage(cb: (err: Error, res: ITabpage) => void): void\n        setCurrentTabpage(tabpage: ITabpage, cb: (err: Error) => void): void\n        subscribe(event: string, cb: (err: Error) => void): void\n        unsubscribe(event: string, cb: (err: Error) => void): void\n        nameToColor(name: string, cb: (err: Error, res: number) => void): void\n        getColorMap(cb: (err: Error, res: {}) => void): void\n        getApiInfo(cb: (err: Error, res: any[]) => void): void\n    }\n\n    interface IBuffer {\n        lineCount(cb: (err: Error, res: number) => void): void\n        getLine(index: number, cb: (err: Error, res: string) => void): void\n        setLine(index: number, line: string, cb: (err: Error) => void): void\n        delLine(index: number, cb: (err: Error) => void): void\n        getLineSlice(\n            start: number,\n            end: number,\n            includeStart: boolean,\n            includeEnd: boolean,\n            cb: (err: Error, res: string[]) => void,\n        ): void\n        getLines(\n            start: number,\n            end: number,\n            strictIndexing: boolean,\n            cb: (err: Error, res: string[]) => void,\n        ): void\n        setLineSlice(\n            start: number,\n            end: number,\n            includeStart: boolean,\n            includeEnd: boolean,\n            replacement: string[],\n            cb: (err: Error) => void,\n        ): void\n        setLines(\n            start: number,\n            end: number,\n            strictIndexing: boolean,\n            replacement: string[],\n            cb: (err: Error) => void,\n        ): void\n        getVar(name: string, cb: (err: Error, res: Object) => void): void\n        setVar(name: string, value: Object, cb: (err: Error, res: Object) => void): void\n        delVar(name: string, cb: (err: Error, res: Object) => void): void\n        getOption(name: string, cb: (err: Error, res: Object) => void): void\n        setOption(name: string, value: Object, cb: (err: Error) => void): void\n        getNumber(cb: (err: Error, res: number) => void): void\n        getName(cb: (err: Error, res: string) => void): void\n        setName(name: string, cb: (err: Error) => void): void\n        isValid(cb: (err: Error, res: boolean) => void): void\n        insert(lnum: number, lines: string[], cb: (err: Error) => void): void\n        getMark(name: string, cb: (err: Error, res: number[]) => void): void\n        addHighlight(\n            srcId: number,\n            hlGroup: string,\n            line: number,\n            colStart: number,\n            colEnd: number,\n            cb: (err: Error, res: number) => void,\n        ): void\n        clearHighlight(\n            srcId: number,\n            lineStart: number,\n            lineEnd: number,\n            cb: (err: Error) => void,\n        ): void\n    }\n\n    interface IWindow {\n        getBuffer(cb: (err: Error, res: IBuffer) => void): void\n        getCursor(cb: (err: Error, res: number[]) => void): void\n        setCursor(pos: number[], cb: (err: Error) => void): void\n        getHeight(cb: (err: Error, res: number) => void): void\n        setHeight(height: number, cb: (err: Error) => void): void\n        getWidth(cb: (err: Error, res: number) => void): void\n        setWidth(width: number, cb: (err: Error) => void): void\n        getVar(name: string, cb: (err: Error, res: Object) => void): void\n        setVar(name: string, value: Object, cb: (err: Error, res: Object) => void): void\n        delVar(name: string, cb: (err: Error, res: Object) => void): void\n        getOption(name: string, cb: (err: Error, res: Object) => void): void\n        setOption(name: string, value: Object, cb: (err: Error) => void): void\n        getPosition(cb: (err: Error, res: number[]) => void): void\n        getTabpage(cb: (err: Error, res: ITabpage) => void): void\n        isValid(cb: (err: Error, res: boolean) => void): void\n    }\n\n    interface ITabpage {\n        getWindows(cb: (err: Error, res: IWindow[]) => void): void\n        getVar(name: string, cb: (err: Error, res: Object) => void): void\n        setVar(name: string, value: Object, cb: (err: Error, res: Object) => void): void\n        delVar(name: string, cb: (err: Error, res: Object) => void): void\n        getWindow(cb: (err: Error, res: IWindow) => void): void\n        isValid(cb: (err: Error, res: boolean) => void): void\n    }\n}\n"
  },
  {
    "path": "browser/src/overlay.less",
    "content": "#overlay-ui {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n}\n\n.overlay-container {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    right: 0px;\n    bottom: 0px;\n    overflow: hidden;\n}\n\n#background,\n.background-image,\n.background-cover {\n    width: 100%;\n    height: 100%;\n    position: absolute;\n}\n"
  },
  {
    "path": "browser/src/startEditors.ts",
    "content": "/**\n * startEditors.ts\n *\n * Initialization for the core set of editors\n */\n\nimport { OniEditor } from \"./Editor/OniEditor\"\n\nimport { PluginManager } from \"./Plugins/PluginManager\"\n\nimport { Colors } from \"./Services/Colors\"\nimport { CompletionProviders } from \"./Services/Completion\"\nimport { Configuration } from \"./Services/Configuration\"\nimport { IDiagnosticsDataSource } from \"./Services/Diagnostics\"\nimport { LanguageManager } from \"./Services/Language\"\nimport { MenuManager } from \"./Services/Menu\"\nimport { OverlayManager } from \"./Services/Overlay\"\nimport { SnippetManager } from \"./Services/Snippets\"\nimport { ThemeManager } from \"./Services/Themes\"\nimport { TokenColors } from \"./Services/TokenColors\"\nimport { windowManager } from \"./Services/WindowManager\"\nimport { Workspace } from \"./Services/Workspace\"\n\nexport const startEditors = async (\n    args: any,\n    colors: Colors,\n    completionProviders: CompletionProviders,\n    configuration: Configuration,\n    diagnostics: IDiagnosticsDataSource,\n    languageManager: LanguageManager,\n    menuManager: MenuManager,\n    overlayManager: OverlayManager,\n    pluginManager: PluginManager,\n    snippetManager: SnippetManager,\n    themeManager: ThemeManager,\n    tokenColors: TokenColors,\n    workspace: Workspace,\n): Promise<void> => {\n    const editor = new OniEditor(\n        colors,\n        completionProviders,\n        configuration,\n        diagnostics,\n        languageManager,\n        menuManager,\n        overlayManager,\n        pluginManager,\n        snippetManager,\n        themeManager,\n        tokenColors,\n        workspace,\n    )\n    windowManager.createSplit(\"horizontal\", editor)\n\n    await editor.init(args)\n}\n"
  },
  {
    "path": "browser/src/sudo-prompt.d.ts",
    "content": "type Callback = (err: Error, stdout: string, stderr: string) => any\n\ndeclare module \"sudo-prompt\" {\n    const exec = (command: string, options: any, cb: Callback) => any\n}\n"
  },
  {
    "path": "browser/src/units-css.d.ts",
    "content": "declare module \"units-css\"\n"
  },
  {
    "path": "browser/test/AppTests.ts",
    "content": "import * as assert from \"assert\"\nimport { remote } from \"electron\"\nimport * as sinon from \"sinon\"\nimport { quit } from \"../src/App\"\n\ndescribe(\"App\", () => {\n    describe(\"oni.quit\", () => {\n        it(\"should invoke remote.app.quit() on Mac\", async () => {\n            // Stub remote.app.quit() function\n            const originalQuit = remote.app.quit\n            const quitStub = sinon.stub()\n            remote.app.quit = quitStub\n            // Stub process.platform\n            const originalPlatform = Object.getOwnPropertyDescriptor(process, \"platform\")\n            Object.defineProperty(process, \"platform\", { value: \"darwin\" })\n            // Test quit()\n            await quit()\n            assert.ok(quitStub.called)\n            // Restore stubs\n            remote.app.quit = originalQuit\n            Object.defineProperty(process, \"platform\", originalPlatform)\n        })\n\n        it(\"shouldn't invoke remote.app.quit() except on Mac\", async () => {\n            // Stub remote.app.quit() function\n            const originalQuit = remote.app.quit\n            const quitStub = sinon.stub()\n            remote.app.quit = quitStub\n            // Stub process.platform\n            const originalPlatform = Object.getOwnPropertyDescriptor(process, \"platform\")\n            Object.defineProperty(process, \"platform\", { value: \"win32\" })\n            // Test quit()\n            await quit()\n            assert.ok(quitStub.notCalled)\n            // Restore stubs\n            remote.app.quit = originalQuit\n            Object.defineProperty(process, \"platform\", originalPlatform)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Editor/NeovimEditor/BufferStateTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as Mocks from \"./../../Mocks\"\n\nimport { checkTabBuffers } from \"./../../../src/UI/components/Tabs\"\n\ndescribe(\"BufferStateTests\", () => {\n    describe(\"tabState\", () => {\n        let mockEditor: Mocks.MockEditor\n        let mockBuffer1: Mocks.MockBuffer\n        let mockBuffer2: Mocks.MockBuffer\n        let mockBuffer3: Mocks.MockBuffer\n\n        beforeEach(() => {\n            mockEditor = new Mocks.MockEditor()\n            mockBuffer1 = new Mocks.MockBuffer(\"typescript\", \"test.ts\", [\"\"])\n            mockBuffer2 = new Mocks.MockBuffer(\"typescript\", \"test2.ts\", [\"\"], 2)\n            mockBuffer3 = new Mocks.MockBuffer(\"typescript\", \"test3.ts\", [\"\"], 3)\n\n            mockEditor.simulateBufferEnter(mockBuffer1)\n            mockBuffer1.setLinesSync([\"Buffer 1 has been altered.\"])\n        })\n\n        it(\"Modified buffer is correctly linked to tab\", () => {\n            const buffers = [mockBuffer1, mockBuffer2, mockBuffer3] as any\n            const buffersInTabs = [1, 2]\n\n            const result = checkTabBuffers(buffersInTabs, buffers)\n\n            assert(result, \"Modified buffer correctly linked\")\n        })\n\n        it(\"Unmodified buffer is correctly linked to tab\", () => {\n            const buffers = [mockBuffer1, mockBuffer2, mockBuffer3] as any\n            const buffersInTabs = [3]\n\n            const result = checkTabBuffers(buffersInTabs, buffers)\n\n            assert(!result, \"Unmodified buffer correctly linked\")\n        })\n\n        it(\"Passing over empty arrays works correctly\", () => {\n            const buffers = [] as any\n            const buffersInTabs = [] as number[]\n\n            const result = checkTabBuffers(buffersInTabs, buffers)\n\n            assert(!result, \"No buffers correctly linked\")\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Editor/NeovimEditor/NeovimEditorReducerTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as Actions from \"./../../../src/Editor/NeovimEditor/NeovimEditorActions\"\nimport {\n    layersReducer,\n    windowStateReducer,\n} from \"./../../../src/Editor/NeovimEditor/NeovimEditorReducer\"\nimport * as State from \"./../../../src/Editor/NeovimEditor/NeovimEditorStore\"\n\ndescribe(\"NeovimEditorReducer\", () => {\n    describe(\"layersReducer\", () => {\n        const simpleLayer: Oni.BufferLayer = {\n            id: \"test\",\n            friendlyName: \"Test\",\n            render(): JSX.Element {\n                return null\n            },\n        }\n\n        it(\"Adds layer via 'ADD_BUFFER_LAYER'\", () => {\n            const addLayerAction = Actions.addBufferLayer(1, simpleLayer)\n\n            const newState = layersReducer({}, addLayerAction)\n\n            const layers = newState[1]\n            assert.deepEqual(layers, [simpleLayer], \"Verify layer was added\")\n        })\n\n        it(\"Removes layer via 'REMOVE_BUFFER_LAYER'\", () => {\n            const stateWithLayer: State.Layers = {\n                1: [simpleLayer],\n            }\n\n            const removeLayerAction = Actions.removeBufferLayer(1, simpleLayer)\n            const stateWithoutLayer = layersReducer(stateWithLayer, removeLayerAction)\n\n            const layers = stateWithoutLayer[1]\n\n            assert.deepEqual(layers, [], \"Verify layer was removed\")\n        })\n    })\n\n    describe(\"windowStateReducer\", () => {\n        it(\"Sets inactive window state via 'SET_INACTIVE_WINDOW_STATE'\", () => {\n            const windowState: State.IWindowState = {\n                activeWindow: -1,\n                windows: {},\n            }\n\n            const windowRect = { x: 1, y: 1, width: 5, height: 5 }\n            const action = Actions.setInactiveWindowState(1, windowRect)\n\n            const newState = windowStateReducer(windowState, action)\n\n            assert.deepEqual(newState.windows[1].dimensions, windowRect)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Editor/NeovimEditor/SymbolsTests.ts",
    "content": "import * as assert from \"assert\"\nimport * as path from \"path\"\nimport * as sinon from \"sinon\"\n\nimport { Event } from \"oni-types\"\nimport { ErrorCodes } from \"vscode-jsonrpc/lib/messages\"\n\nimport { Definition } from \"../../../src/Editor/NeovimEditor/Definition\"\nimport { Symbols } from \"../../../src/Editor/NeovimEditor/Symbols\"\nimport { wrapPathInFileUri } from \"../../../src/Plugins/Api/LanguageClient/LanguageClientHelpers\"\nimport { LanguageManager } from \"../../../src/Services/Language\"\nimport { Menu, MenuManager } from \"../../../src/Services/Menu\"\n\n/* tslint:disable:no-string-literal */\n\nconst clock: any = global[\"clock\"] // tslint:disable-line\nconst waitForPromiseResolution: any = global[\"waitForPromiseResolution\"] // tslint:disable-line\n\ndescribe(\"Symbols\", () => {\n    let editor: any\n    let definition: any\n    let languageManager: any\n    let menuManager: any\n    let symbols: any\n\n    beforeEach(() => {\n        editor = sinon.stub()\n        editor.activeBuffer = \"mock buffer\"\n        definition = sinon.createStubInstance(Definition)\n        languageManager = sinon.createStubInstance(LanguageManager)\n        menuManager = sinon.createStubInstance(MenuManager)\n\n        symbols = new Symbols(editor, definition, languageManager, menuManager)\n    })\n\n    describe(\"open workspace/document menus\", () => {\n        let menu: any\n        let onFilterTextChanged: Event<string>\n        let onItemSelected: Event<string>\n\n        beforeEach(() => {\n            menu = sinon.createStubInstance(Menu)\n            onFilterTextChanged = new Event<string>()\n            onItemSelected = new Event<string>()\n            sinon.stub(menu, \"onItemSelected\").get(() => onItemSelected)\n            sinon.stub(menu, \"onFilterTextChanged\").get(() => onFilterTextChanged)\n            menuManager.create.returns(menu)\n\n            symbols[\"_requestSymbols\"] = sinon.stub().resolves([\"first symbol\", \"second symbol\"])\n            const _symbolInfoToMenuItem = sinon.stub()\n            _symbolInfoToMenuItem.onCall(0).returns(\"first transformed\")\n            _symbolInfoToMenuItem.onCall(1).returns(\"second transformed\")\n            symbols[\"_symbolInfoToMenuItem\"] = _symbolInfoToMenuItem\n        })\n\n        describe(\"openWorkspaceSymbolsMenu\", () => {\n            let getKey: any\n\n            beforeEach(() => {\n                getKey = sinon.stub()\n                symbols[\"_getDetailFromSymbol\"] = sinon.stub().returns(getKey)\n            })\n\n            it(\"requests workspace symbols when filter text is changed\", async () => {\n                // setup\n                symbols.openWorkspaceSymbolsMenu()\n                clock.tick(30)\n                sinon.assert.notCalled(symbols[\"_requestSymbols\"])\n\n                // action\n                onFilterTextChanged.dispatch(\"mock query\")\n\n                // confirm\n                clock.tick(24)\n                sinon.assert.notCalled(symbols[\"_requestSymbols\"])\n                clock.tick(1)\n                sinon.assert.calledWithExactly(\n                    symbols[\"_requestSymbols\"],\n                    \"mock buffer\",\n                    \"workspace/symbol\",\n                    menu,\n                    { query: \"mock query\" },\n                )\n                await waitForPromiseResolution()\n                assertCommon()\n            })\n        })\n\n        describe(\"openDocumentSymbolsMenu\", () => {\n            it(\"requests document symbols when completion menu is opened\", async () => {\n                // action\n                await symbols.openDocumentSymbolsMenu()\n\n                // confirm\n                sinon.assert.calledWithExactly(\n                    symbols[\"_requestSymbols\"],\n                    \"mock buffer\",\n                    \"textDocument/documentSymbol\",\n                    menu,\n                )\n                assertCommon()\n            })\n        })\n\n        const assertCommon = () => {\n            assert.deepEqual(symbols[\"_symbolInfoToMenuItem\"].args, [\n                [\"first symbol\"],\n                [\"second symbol\"],\n            ])\n            sinon.assert.calledWithExactly(menu.setItems.lastCall, [\n                \"first transformed\",\n                \"second transformed\",\n            ])\n        }\n    }) // End describe open menus\n\n    describe(\"_requestSymbols\", () => {\n        let menu: any\n        let buffer: any\n\n        beforeEach(() => {\n            menu = sinon.createStubInstance(Menu)\n            menu.isOpen.returns(true)\n            buffer = sinon.stub()\n            buffer.language = \"mocklang\"\n            buffer.filePath = path.join(\"mock\", \"path\")\n        })\n\n        it(\"throws on unknown errors\", async () => {\n            // setup\n            const error = new Error()\n            languageManager.sendLanguageServerRequest.throws(error)\n\n            try {\n                // action\n                await symbols[\"_requestSymbols\"](buffer, \"mock command\", menu)\n\n                // confirm\n                assert.fail(\"Expected exception to be thrown\")\n            } catch (e) {\n                assert.strictEqual(e, error)\n            }\n        })\n\n        it(\"retries whilst server is initialising\", async () => {\n            // setup\n            const error: any = new Error()\n            error.code = ErrorCodes.ServerNotInitialized\n            languageManager.sendLanguageServerRequest.onCall(0).throws(error)\n            languageManager.sendLanguageServerRequest.onCall(1).throws(error)\n            languageManager.sendLanguageServerRequest.onCall(2).returns(\"mock result\")\n\n            // action\n            const request: Promise<any> = symbols[\"_requestSymbols\"](buffer, \"mock command\", menu, {\n                mock: \"option\",\n            })\n\n            // confirm\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 1)\n            clock.tick(999)\n            await waitForPromiseResolution()\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 1)\n            clock.tick(1)\n            await waitForPromiseResolution()\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 2)\n            clock.tick(1000)\n            await waitForPromiseResolution()\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 3)\n            clock.tick(1000)\n            await waitForPromiseResolution()\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 3)\n            clock.tick(1000)\n            await waitForPromiseResolution()\n            sinon.assert.alwaysCalledWith(\n                languageManager.sendLanguageServerRequest,\n                \"mocklang\",\n                buffer.filePath,\n                \"mock command\",\n                { mock: \"option\", textDocument: { uri: wrapPathInFileUri(buffer.filePath) } },\n            )\n            assert.equal(await request, \"mock result\")\n        })\n\n        it(\"gives up retrying if menu is closed\", async () => {\n            // setup\n            const error: any = new Error()\n            error.code = ErrorCodes.ServerNotInitialized\n            languageManager.sendLanguageServerRequest.throws(error)\n\n            // action\n            const request: Promise<any> = symbols[\"_requestSymbols\"](buffer, \"mock command\", menu)\n\n            // confirm\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 1)\n            clock.tick(1000)\n            await waitForPromiseResolution()\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 2)\n            menu.isOpen.returns(false)\n            clock.tick(1000)\n            await waitForPromiseResolution()\n            sinon.assert.callCount(languageManager.sendLanguageServerRequest, 2)\n\n            const result = await request\n\n            assert.deepEqual(result, [])\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/GridTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport { Grid } from \"./../src/Grid\"\n\ndescribe(\"Grid\", () => {\n    it(\"getCell returns correct value\", () => {\n        const grid = new Grid<string>()\n\n        grid.setCell(1, 1, \"a\")\n\n        assert.strictEqual(grid.getCell(0, 0), null)\n        assert.strictEqual(grid.getCell(1, 1), \"a\")\n    })\n\n    it(\"width and height are 0 by default\", () => {\n        const grid = new Grid<void>()\n\n        assert.strictEqual(grid.width, 0)\n        assert.strictEqual(grid.height, 0)\n    })\n\n    describe(\"shift\", () => {\n        it(\"shift(0) does not shift\", () => {\n            const val = [[1, 2], [3, 4]]\n\n            const startGrid = createGridFromNestedArray(val)\n            startGrid.shiftRows(0)\n            assertGridValues(startGrid, val)\n        })\n\n        it(\"shift(1) shifts upwards\", () => {\n            const val = [[1, 2], [3, 4]]\n\n            const startGrid = createGridFromNestedArray(val)\n            startGrid.shiftRows(1)\n\n            const expectedOutput = [[3, 4], [null, null]]\n            assertGridValues(startGrid, expectedOutput)\n        })\n\n        it(\"shift(-1) shifts downwards\", () => {\n            const val = [[1, 2], [3, 4]]\n\n            const startGrid = createGridFromNestedArray(val)\n            startGrid.shiftRows(-1)\n\n            const expectedOutput = [[null, null], [1, 2]]\n            assertGridValues(startGrid, expectedOutput)\n        })\n    })\n\n    describe(\"setRegion\", () => {\n        it(\"sets value\", () => {\n            const val = [[1, 2], [3, 4]]\n\n            const startGrid = createGridFromNestedArray(val)\n\n            startGrid.setRegion(0, 0, 2, 2, 5)\n\n            const expectedVal = [[5, 5], [5, 5]]\n\n            assertGridValues(startGrid, expectedVal)\n        })\n\n        it(\"sets null correctly\", () => {\n            const val = [[1, 2, 3], [3, 4, 5], [6, 7, 8]]\n\n            const startGrid = createGridFromNestedArray(val)\n\n            startGrid.setRegion(0, 0, 2, 2, null)\n\n            const expectedOuput = [[null, null, 3], [null, null, 5], [6, 7, 8]]\n\n            assertGridValues(startGrid, expectedOuput)\n        })\n    })\n\n    describe(\"cloneRegion\", () => {\n        it(\"returns new grid for single item\", () => {\n            const val = [[1, 2], [3, 4]]\n\n            const startGrid = createGridFromNestedArray(val)\n\n            const topLeftGrid = startGrid.cloneRegion(0, 0, 1, 1)\n            assert.strictEqual(topLeftGrid.width, 1)\n            assert.strictEqual(topLeftGrid.height, 1)\n            assert.strictEqual(topLeftGrid.getCell(0, 0), 1)\n\n            const bottomRightGrid = startGrid.cloneRegion(1, 1, 1, 1)\n            assert.strictEqual(bottomRightGrid.width, 1)\n            assert.strictEqual(bottomRightGrid.height, 1)\n            assert.strictEqual(bottomRightGrid.getCell(0, 0), 4)\n        })\n\n        it(\"returns square subsection\", () => {\n            const val = [[1, 2, 3], [3, 4, 5], [6, 7, 8]]\n\n            const startGrid = createGridFromNestedArray(val)\n\n            const topLeftGrid = startGrid.cloneRegion(0, 0, 2, 2)\n            assert.strictEqual(topLeftGrid.width, 2)\n            assert.strictEqual(topLeftGrid.height, 2)\n\n            const expectedOutput = [[1, 2], [3, 4]]\n\n            assertGridValues(topLeftGrid, expectedOutput)\n        })\n\n        it(\"handles null & undefined correctly\", () => {\n            const val = [[null, undefined, 3], [0, 1, 5], [6, 7, 8]]\n\n            const startGrid = createGridFromNestedArray(val)\n            const outGrid = startGrid.cloneRegion(0, 0, 2, 2)\n\n            const expectedOutput = [[null, null], [0, 1]]\n\n            assertGridValues(outGrid, expectedOutput)\n        })\n    })\n})\n\nfunction createGridFromNestedArray<T>(array: T[][]): Grid<T> {\n    const grid = new Grid<T>()\n\n    for (let row = 0; row < array.length; row++) {\n        const rowItems = array[row]\n\n        for (let col = 0; col < rowItems.length; col++) {\n            const colItem = rowItems[col]\n\n            grid.setCell(col, row, colItem)\n        }\n    }\n\n    return grid\n}\n\nfunction assertGridValues<T>(grid: Grid<T>, array: T[][]): void {\n    for (let row = 0; row < array.length; row++) {\n        const rowItems = array[row]\n\n        for (let col = 0; col < rowItems.length; col++) {\n            // var colItem = rowItems[col]\n\n            const item = grid.getCell(col, row)\n            assert.strictEqual(item, array[row][col], `Validate item at row: ${row} and ${col}`)\n        }\n    }\n}\n"
  },
  {
    "path": "browser/test/Input/InputManagerTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport { getRecentKeyPresses, InputManager, KeyPressInfo } from \"./../../src/Services/InputManager\"\n\ndescribe(\"InputManager\", () => {\n    describe(\"bind\", () => {\n        it(\"adds a key handler\", () => {\n            const im = new InputManager()\n\n            let count = 0\n            im.bind(\"<c-a>\", () => {\n                count++\n                return true\n            })\n\n            const handled = im.handleKey(\"<c-a>\")\n\n            assert.strictEqual(count, 1, \"Validate handler was called\")\n            assert.strictEqual(handled, true)\n        })\n\n        it(\"removes key handler when calling dispose\", () => {\n            const im = new InputManager()\n\n            let count = 0\n            const dispose = im.bind(\"<c-a>\", () => {\n                count++\n                return true\n            })\n            dispose()\n\n            const handled = im.handleKey(\"<c-a>\")\n\n            assert.strictEqual(count, 0, \"Handler should not have been called\")\n            assert.strictEqual(handled, false)\n        })\n\n        it(\"dispose key handler is robust if unbindAll was called first\", () => {\n            const im = new InputManager()\n\n            let count = 0\n            const dispose = im.bind(\"{\", () => {\n                count++\n                return true\n            })\n\n            im.unbindAll()\n\n            dispose()\n\n            const handled = im.handleKey(\"{\")\n            assert.strictEqual(count, 0, \"Handler should not have been called.\")\n            assert.strictEqual(handled, false)\n        })\n\n        it(\"can unbind an array of keys\", () => {\n            const im = new InputManager()\n            im.bind([\"a\", \"b\"], \"test.command\")\n            im.unbind([\"a\", \"b\"])\n\n            const boundKeys = im.getBoundKeys(\"test.command\")\n            assert.deepEqual(boundKeys, [], \"Validate no bound keys are returned\")\n        })\n\n        describe(\"getBoundKeys\", () => {\n            it(\"returns empty array if no key bound to command\", () => {\n                const im = new InputManager()\n\n                const boundKeys = im.getBoundKeys(\"test.command\")\n                assert.deepEqual(boundKeys, [], \"Validate no keys bound\")\n            })\n\n            it(\"returns key bound to command\", () => {\n                const im = new InputManager()\n                im.bind(\"<c-a>\", \"test.command\")\n\n                const boundKeys = im.getBoundKeys(\"test.command\")\n                assert.deepEqual(boundKeys, [\"<c-a>\"], \"Validate the bound key is returned\")\n            })\n\n            it(\"does not return key if bound and then unbind\", () => {\n                const im = new InputManager()\n                const unbind = im.bind(\"<c-a>\", \"test.command\")\n\n                unbind()\n\n                const boundKeys = im.getBoundKeys(\"test.command\")\n                assert.deepEqual(boundKeys, [], \"Validate no bound keys are returned\")\n            })\n        })\n    })\n\n    describe(\"handleKey\", () => {\n        it(\"handles chorded inputs\", () => {\n            const im = new InputManager()\n\n            let hitCount: number = 0\n            im.bind(\"gg\", () => {\n                hitCount++\n                return true\n            })\n\n            im.handleKey(\"g\", 1)\n            im.handleKey(\"g\", 2)\n\n            assert.strictEqual(hitCount, 1, \"Validate the binding for gg was executed\")\n        })\n\n        it(\"doesn't dispatch action if time expires between key presses\", () => {\n            const im = new InputManager()\n\n            let hitCount: number = 0\n            im.bind(\"gg\", () => {\n                hitCount++\n                return true\n            })\n\n            im.handleKey(\"g\", 1)\n            im.handleKey(\"g\", 1000)\n\n            assert.strictEqual(hitCount, 0, \"Validate the binding was not executed\")\n        })\n\n        it(\"doesn't re-dispatch if key was null\", () => {\n            const im = new InputManager()\n            let hitCount: number = 0\n            im.bind(\"[\", () => {\n                hitCount++\n                return true\n            })\n\n            im.handleKey(\"[\", 1)\n\n            // For control keys like 'shift', we get a null value passed\n            // to the key-chord logic.\n            im.handleKey(null, 2)\n\n            assert.strictEqual(hitCount, 1, \"Verify handler was only hit once\")\n        })\n    })\n\n    describe(\"getRecentKeyPresses\", () => {\n        const createKeyPressInfo = (keyChord: string, time: number): KeyPressInfo => ({\n            keyChord,\n            time,\n        })\n        it(\"collapses keypress info per the delay\", () => {\n            const key1 = createKeyPressInfo(\"a\", 1)\n            const key2 = createKeyPressInfo(\"b\", 2)\n            const key3 = createKeyPressInfo(\"c\", 103)\n            const key4 = createKeyPressInfo(\"d\", 104)\n\n            const items = getRecentKeyPresses([key1, key2, key3, key4], 100)\n\n            assert.deepEqual(items, [key3, key4], \"Validate the correct items remain\")\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Input/KeyParserTests.ts",
    "content": "/**\n * KeyParserTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport * as KeyParser from \"./../../src/Input/KeyParser\"\n\ndescribe(\"KeyParser\", () => {\n    describe(\"parseKeysFromVimString\", () => {\n        it(\"parses a basic key\", () => {\n            const result = KeyParser.parseKeysFromVimString(\"a\")\n\n            assert.deepEqual(result.chord, [\n                { character: \"a\", shift: false, alt: false, control: false, meta: false },\n            ])\n        })\n\n        it(\"parses multiple keys in a row\", () => {\n            const result = KeyParser.parseKeysFromVimString(\"ab\")\n            assert.deepEqual(result.chord, [\n                { character: \"a\", shift: false, alt: false, control: false, meta: false },\n                { character: \"b\", shift: false, alt: false, control: false, meta: false },\n            ])\n        })\n\n        it(\"parses modifier keys\", () => {\n            const result = KeyParser.parseKeysFromVimString(\"<c-a>\")\n            assert.deepEqual(result.chord, [\n                { character: \"a\", shift: false, alt: false, control: true, meta: false },\n            ])\n        })\n    })\n\n    describe(\"parseChordParts\", () => {\n        it(\"parses modifier keys\", () => {\n            const tests: Array<[string, string[]]> = [\n                [\"a\", [\"a\"]],\n                [\"<c-a>\", [\"control\", \"a\"]],\n                [\"<m-a>\", [\"meta\", \"a\"]],\n                [\"<a-a>\", [\"alt\", \"a\"]],\n                [\"<s-a>\", [\"shift\", \"a\"]],\n                [\"<m-c-a-s-a>\", [\"meta\", \"control\", \"alt\", \"shift\", \"a\"]],\n            ]\n\n            tests.forEach(test => {\n                assert.deepEqual(KeyParser.parseChordParts(test[0]), test[1])\n            })\n        })\n\n        it(\"ignores keys beyond the first chord\", () => {\n            const result = KeyParser.parseChordParts(\"<c-a>b\")\n            assert.deepEqual(result, [\"control\", \"a\"])\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Input/Keyboard/ResolverTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport {\n    createMetaKeyResolver,\n    ignoreMetaKeyResolver,\n    KeyResolver,\n    remapResolver,\n} from \"./../../../src/Input/Keyboard/Resolvers\"\n\ndescribe(\"Resolvers\", () => {\n    describe(\"ignoreMetaResolver\", () => {\n        it(\"ignores key in blacklist\", () => {\n            const result = ignoreMetaKeyResolver(keyShift, \"Shift\")\n            assert.equal(result, null)\n        })\n\n        it(\"passes through key not in blacklist\", () => {\n            const result = ignoreMetaKeyResolver(keyS, \"s\")\n            assert.equal(result, \"s\")\n        })\n    })\n\n    describe(\"remapResolver\", () => {\n        it(\"remaps Backspace key\", () => {\n            const result = remapResolver(keyBackSpace, \"Backspace\")\n            assert.equal(result, \"bs\")\n        })\n\n        it(\"remaps Space key\", () => {\n            const result = remapResolver(keySpace, \" \")\n            assert.equal(result, \"space\")\n        })\n    })\n\n    describe(\"metaResolver\", () => {\n        let metaResolver: KeyResolver\n\n        describe(\"*\", () => {\n            it(\"Handles <s- > (shift+space)\", () => {\n                const layout = {\n                    Space: {\n                        unmodified: \" \",\n                        withShift: \" \",\n                    },\n                }\n\n                metaResolver = createMetaKeyResolver(layout)\n\n                const key = shift(createKeyEvent(\" \", \"Space\"))\n                const result = metaResolver(key, key.key)\n                assert.equal(result, \"<s- >\")\n            })\n        })\n\n        describe(\"english\", () => {\n            beforeEach(() => {\n                metaResolver = createMetaKeyResolver(englishLayout)\n            })\n\n            it(\"Handles <c-s-p>\", () => {\n                const key = control(shift(keyP))\n                const result = metaResolver(key, keyP.key)\n\n                assert.equal(result, \"<s-c-p>\")\n            })\n        })\n\n        describe(\"english-intl\", () => {\n            beforeEach(() => {\n                metaResolver = createMetaKeyResolver(englishInternationalLayout)\n            })\n\n            it(\"handles §\", () => {\n                const key = control(alt(shift(createKeyEvent(\"§\", \"KeyS\"))))\n                const result = metaResolver(key, key.key)\n                assert.equal(result, \"§\")\n            })\n        })\n\n        describe(\"german\", () => {\n            beforeEach(() => {\n                metaResolver = createMetaKeyResolver(germanLayout)\n            })\n\n            it(\"Handles ö\", () => {\n                const key = keyUmlautedO\n                const result = metaResolver(key, key.key)\n\n                assert.equal(result, \"ö\")\n            })\n\n            it(\"Handles Ö\", () => {\n                const key = shift(keyUmlautedO)\n                const result = metaResolver(key, key.key)\n\n                assert.equal(result, \"Ö\")\n            })\n        })\n    })\n})\n\nconst englishLayout = {\n    KeyP: {\n        unmodified: \"p\",\n        withShift: \"P\",\n    },\n}\n\nconst englishInternationalLayout = {\n    KeyS: {\n        unmodified: \"s\",\n        withShift: \"S\",\n        withAltGraph: \"ß\",\n        withAltGraphShift: \"§\",\n    },\n}\n\nconst germanLayout = {\n    Semicolon: {\n        unmodified: \"ö\",\n        withShift: \"Ö\",\n    },\n}\n\nconst createKeyEvent = (key: string, code: string): any => ({\n    key,\n    code,\n    ctrlKey: false,\n    altKey: false,\n    shiftKey: false,\n    preventDefault: () => {}, // tslint:disable-line no-empty\n})\n\nconst control = (keyEvent: KeyboardEvent): KeyboardEvent => ({\n    ...keyEvent,\n    ctrlKey: true,\n})\n\nconst alt = (keyEvent: KeyboardEvent): KeyboardEvent => ({\n    ...keyEvent,\n    altKey: true,\n})\n\nconst shift = (keyEvent: KeyboardEvent): KeyboardEvent => ({\n    ...keyEvent,\n    key: keyEvent.key.length === 1 ? keyEvent.key.toUpperCase() : keyEvent.key,\n    shiftKey: true,\n})\n\nconst keyBackSpace = createKeyEvent(\"Backspace\", \"Backspace\")\nconst keyShift = shift(createKeyEvent(\"Shift\", \"Shift\"))\nconst keyS = createKeyEvent(\"s\", \"KeyS\")\nconst keyP = createKeyEvent(\"p\", \"KeyP\")\nconst keyUmlautedO = createKeyEvent(\"ö\", \"Semicolon\")\nconst keySpace = createKeyEvent(\" \", \" \")\n"
  },
  {
    "path": "browser/test/MarkdownTests.ts",
    "content": "import * as assert from \"assert\"\nimport { unescape } from \"lodash\"\nimport { StackElement } from \"vscode-textmate\"\nimport * as markdown from \"./../../browser/src/Editor/NeovimEditor/markdown\"\n\ndescribe(\"Markdown Conversion Functions\", () => {\n    it(\"Scopes to string fn should correctly convert scopes to classnames\", () => {\n        const className = markdown.scopesToString([\"token.scope.extension\"])\n        assert.ok(className === \"token-scope\")\n    })\n\n    it(\"Scopes to string fn should correctly convert single words to a className\", () => {\n        const className = markdown.scopesToString([\"source\"])\n        assert.ok(className === \"source\")\n    })\n\n    it(\"Scopes to string Should return null if passed an falsy\", () => {\n        const nullArg = markdown.scopesToString(null)\n        assert.ok(!nullArg)\n    })\n\n    it(\"Escape RegExp function should add an escape character to all banned chars\", () => {\n        const stringForRegex = \"*apple^\"\n        const escaped = markdown.escapeRegExp(stringForRegex)\n        // prettier-ignore\n        assert.ok(escaped === \"\\\\*apple\\\\^\")\n    })\n    it(\"Escape RegExp function should NOT add an escape character to the | or - characters\", () => {\n        // NOTE token names include either so if they are escaped the token matching will fail\n        const stringForRegex = \"apple-tree|pineapple\"\n        const notEscaped = markdown.escapeRegExp(stringForRegex)\n        assert.ok(notEscaped === \"apple-tree|pineapple\")\n    })\n\n    it(\"Create container function should wrap given text in a paragraph tag\", () => {\n        const wrapped = markdown.createContainer(\"p\", \"this is a paragraph\")\n        assert.ok(wrapped === `<p class=\"marked-paragraph\">this is a paragraph</p>`)\n    })\n\n    it(\"Create container function should wrap given text in a pre element with a code block\", () => {\n        const wrapped = markdown.createContainer(\"pre\", \"this is code\")\n        assert.ok(wrapped === `<pre class=\"marked-pre\">this is code</pre>`)\n    })\n\n    it(\"Should match tokens correctly and wrap a token in a span with the correct class\", () => {\n        const test = \"eight\"\n        const token = [\n            {\n                line: test,\n                ruleStack: {} as StackElement,\n                tokens: [\n                    {\n                        scopes: [\"test.scope.tsx\"],\n                        range: { start: { character: 0, line: 0 }, end: { character: 5, line: 0 } },\n                    },\n                ],\n            },\n        ]\n        const tag = markdown.renderWithClasses({ tokens: token, text: test, container: \"p\" })\n        assert.ok(\n            tag.replace(\"\\n\", \"\") ===\n                `<p class=\"marked-paragraph\"><span class=\"marked test-scope\">eight</span></p>`,\n        )\n    })\n    it(\"Should match several tokens correctly and wrap a token in a span with the correct class\", () => {\n        const tokens = [\n            {\n                line: \"React HTMLElement\",\n                ruleStack: {} as StackElement,\n                tokens: [\n                    {\n                        scopes: [\"react.js.tsx\"],\n                        range: { start: { character: 0, line: 0 }, end: { character: 5, line: 0 } },\n                    },\n                    {\n                        scopes: [\"stack.element.tsx\"],\n                        range: {\n                            start: { character: 6, line: 0 },\n                            end: { character: 17, line: 0 },\n                        },\n                    },\n                ],\n            },\n        ]\n        const tag = markdown.renderWithClasses({\n            tokens,\n            text: \"React HTMLElement\",\n            container: \"code\",\n        })\n        // Note Code block provides its own code tag so this should return just spans\n        const expected = `<span class=\"marked react-js\">React</span> <span class=\"marked stack-element\">HTMLElement</span>`\n            .replace(\"\\n\", \"\")\n            .trim()\n\n        assert.ok(tag.replace(\"\\n\", \"\").trim() === expected)\n    })\n\n    it(\"should render safe jsx untouched \", () => {\n        const md = `### A title\n            <AReactComponent />`\n        const result = markdown.convertMarkdown({ markdown: md, tokens: null })\n        assert.ok(unescape(result).includes(`<AReactComponent />`))\n    })\n\n    it(\"should render safe html untouched \", () => {\n        const md = `### Another Title\n            <div></div>`\n        const result = markdown.convertMarkdown({ markdown: md, tokens: null })\n        assert.ok(unescape(result).includes(`<div></div>`))\n    })\n})\n"
  },
  {
    "path": "browser/test/Mocks/MockBuffer.ts",
    "content": "/**\n * Mocks/index.ts\n *\n * Implementations of test mocks and doubles,\n * to exercise boundaries of class implementations\n */\n\nexport * from \"./MockPluginManager\"\nexport * from \"./MockThemeLoader\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { IBufferHighlightsUpdater } from \"./../../src/Editor/BufferHighlights\"\nimport { BufferIndentationInfo } from \"./../../src/Editor/BufferManager\"\n\nimport { HighlightInfo } from \"./../../src/Services/SyntaxHighlighting\"\n\nexport class MockBuffer {\n    private _mockHighlights = new MockBufferHighlightsUpdater()\n    private _cursor = { line: 0, column: 0 }\n    private _modified = false\n\n    private _indentationInfo: BufferIndentationInfo = {\n        indent: \"   \",\n        type: \"space\",\n        amount: 3,\n    }\n\n    public get id(): number {\n        return this._id\n    }\n\n    public get language(): string {\n        return this._language\n    }\n\n    public get filePath(): string {\n        return this._filePath\n    }\n\n    public get lineCount(): number {\n        return this._lines.length\n    }\n\n    public get mockHighlights(): MockBufferHighlightsUpdater {\n        return this._mockHighlights\n    }\n\n    public get cursor(): Oni.Cursor {\n        return this._cursor\n    }\n\n    public get modified(): boolean {\n        return this._modified\n    }\n\n    public constructor(\n        private _language: string = \"test_language\",\n        private _filePath: string = \"test_filepath\",\n        private _lines: string[] = [],\n        private _id: number = 1,\n    ) {}\n\n    public async detectIndentation(): Promise<BufferIndentationInfo> {\n        return this._indentationInfo\n    }\n\n    public async getCursorPosition(): Promise<types.Position> {\n        return types.Position.create(this._cursor.line, this._cursor.column)\n    }\n\n    public setCursorPosition(line: number, column: number) {\n        this._cursor.column = column\n        this._cursor.line = line\n    }\n\n    public setLinesSync(lines: string[]): void {\n        this._lines = lines\n        this._modified = true\n    }\n\n    public setLineSync(line: number, lineContents: string): void {\n        while (this._lines.length <= line) {\n            this._lines.push(\"\")\n        }\n\n        this._lines[line] = lineContents\n        this._modified = true\n    }\n\n    public setWhitespace(indentationInfo: BufferIndentationInfo): void {\n        this._indentationInfo = indentationInfo\n    }\n\n    public async setLines(start: number, end: number, lines: string[]): Promise<void> {\n        while (this._lines.length <= end) {\n            this._lines.push(\"\")\n        }\n\n        for (let i = 0; i < lines.length; i++) {\n            this._lines[start + i] = lines[i]\n        }\n\n        this._modified = true\n    }\n\n    public getLines(start: number = 0, end?: number): Promise<string[]> {\n        if (typeof end !== \"number\") {\n            end = this._lines.length\n        }\n\n        return Promise.resolve(this._lines.slice(start, end))\n    }\n\n    public updateHighlights(\n        tokenColors: any[],\n        updateFunction: (highlightUpdater: IBufferHighlightsUpdater) => void,\n    ) {\n        updateFunction(this._mockHighlights)\n    }\n\n    public addLayer(): void {\n        // tslint:disable-line\n    }\n\n    public removeLayer(): void {\n        // tslint:disable-line\n    }\n}\n\nexport class MockBufferHighlightsUpdater implements IBufferHighlightsUpdater {\n    private _linesToHighlights: { [line: number]: HighlightInfo[] } = {}\n\n    public setHighlightsForLine(line: number, highlights: HighlightInfo[]): void {\n        this._linesToHighlights[line] = highlights\n    }\n\n    public clearHighlightsForLine(line: number): void {\n        this._linesToHighlights[line] = null\n    }\n\n    public getHighlightsForLine(line: number): HighlightInfo[] {\n        return this._linesToHighlights[line] || []\n    }\n}\n"
  },
  {
    "path": "browser/test/Mocks/MockPersistentStore.ts",
    "content": "/**\n * MockPersistentStore.ts\n */\n\nimport { IPersistentStore } from \"./../../src/PersistentStore\"\n\nexport class MockPersistentStore<T> implements IPersistentStore<T> {\n    private _state: T\n\n    constructor(initialState: T) {\n        this._state = initialState\n    }\n\n    public async set(state: T): Promise<void> {\n        this._state = state\n    }\n\n    public async get(): Promise<T> {\n        return this._state\n    }\n\n    public async delete(key: string): Promise<T> {\n        this._state[key] = undefined\n        return this._state\n    }\n\n    public has(key: string) {\n        return !!this._state[key]\n    }\n}\n"
  },
  {
    "path": "browser/test/Mocks/MockPluginManager.ts",
    "content": "/**\n * Mocks/MockPluginManager.ts\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { IContributions } from \"./../../src/Plugins/Api/Capabilities\"\n\nexport class MockPluginManager implements Oni.IPluginManager {\n    public get loaded(): boolean {\n        return false\n    }\n\n    public discoverPlugins(): void {\n        // tslint:disable-line\n    }\n\n    public getAllContributionsOfType<T>(selector: (capabilities: IContributions) => T[]): T[] {\n        return []\n    }\n\n    public startApi(): Oni.Plugin.Api {\n        return null\n    }\n\n    public getPlugin(name: string): any {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/test/Mocks/MockThemeLoader.ts",
    "content": "/**\n * Mocks/MockThemeLoader.ts\n */\n\nimport { IThemeContribution } from \"./../../src/Plugins/Api/Capabilities\"\nimport { IThemeLoader, IThemeMetadata } from \"./../../src/Services/Themes\"\n\nexport class MockThemeLoader implements IThemeLoader {\n    private _nameToTheme: { [key: string]: IThemeMetadata } = {}\n\n    public getAllThemes(): Promise<IThemeContribution[]> {\n        const themeContributions = Object.keys(this._nameToTheme).map(\n            (name): IThemeContribution => ({\n                name,\n                path: null,\n            }),\n        )\n        return Promise.resolve(themeContributions)\n    }\n\n    public getThemeByName(name: string): Promise<IThemeMetadata> {\n        return Promise.resolve(this._nameToTheme[name])\n    }\n\n    public addTheme(name: string, theme: IThemeMetadata): void {\n        this._nameToTheme[name] = theme\n    }\n}\n"
  },
  {
    "path": "browser/test/Mocks/index.ts",
    "content": "/**\n * Mocks/index.ts\n *\n * Implementations of test mocks and doubles,\n * to exercise boundaries of class implementations\n */\n\nexport * from \"./MockBuffer\"\nexport * from \"./neovim/MockNeovimInstance\"\nexport * from \"./MockPersistentStore\"\nimport { MockPluginManager } from \"./MockPluginManager\"\nexport * from \"./MockThemeLoader\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { Editor } from \"./../../src/Editor/Editor\"\n\nimport { EditorManager } from \"./../../src/Services/EditorManager\"\nimport * as Language from \"./../../src/Services/Language\"\nimport { createCompletablePromise, ICompletablePromise } from \"./../../src/Utility\"\n\nimport { TokenColor } from \"./../../src/Services/TokenColors\"\n\nexport class MockWindowSplit {\n    public get id(): string {\n        return this._id\n    }\n\n    public get innerSplit(): any {\n        return null\n    }\n\n    constructor(private _id: string = \"mock.window\") {}\n\n    public render(): JSX.Element {\n        return null\n    }\n}\n\nexport class MockTokenColors {\n    constructor(private _tokenColors: TokenColor[] = []) {}\n\n    public get tokenColors(): TokenColor[] {\n        return this._tokenColors\n    }\n}\n\nimport { MockBuffer } from \"./MockBuffer\"\n\nexport class MockConfiguration implements Oni.Configuration {\n    private _currentConfigurationFiles: string[] = []\n    private _onConfigurationChanged = new Event<any>()\n\n    public get onConfigurationChanged(): IEvent<any> {\n        return this._onConfigurationChanged\n    }\n\n    public get currentConfigurationFiles(): string[] {\n        return this._currentConfigurationFiles\n    }\n\n    constructor(private _configurationValues: any = {}) {}\n\n    public getValue(key: string): any {\n        return this._configurationValues[key]\n    }\n\n    public setValue(key: string, value: any): void {\n        this._configurationValues[key] = value\n    }\n\n    public setValues(): void {\n        throw Error(\"Not yet implemented\")\n    }\n\n    public addConfigurationFile(filePath: string): void {\n        this._currentConfigurationFiles = [...this._currentConfigurationFiles, filePath]\n    }\n\n    public removeConfigurationFile(filePath: string): void {\n        this._currentConfigurationFiles = this._currentConfigurationFiles.filter(\n            fp => fp !== filePath,\n        )\n    }\n\n    public simulateConfigurationChangedEvent(changedConfigurationValues: any): void {\n        this._onConfigurationChanged.dispatch(changedConfigurationValues)\n    }\n}\n\nexport class MockWorkspace implements Oni.Workspace.Api {\n    private _activeWorkspace: string = null\n    private _onDirectoryChangedEvent = new Event<string>()\n    private _onFocusGainedEvent = new Event<void>()\n    private _onFocusLostEvent = new Event<void>()\n\n    public get onDirectoryChanged(): IEvent<string> {\n        return this._onDirectoryChangedEvent\n    }\n\n    public get onFocusGained(): IEvent<void> {\n        return this._onFocusGainedEvent\n    }\n\n    public get onFocusLost(): IEvent<void> {\n        return this._onFocusLostEvent\n    }\n\n    public get activeWorkspace(): string {\n        return this._activeWorkspace\n    }\n\n    public changeDirectory(newDirectory: string): void {\n        // tslint:disable-line\n\n        this._activeWorkspace = newDirectory\n        this._onDirectoryChangedEvent.dispatch(newDirectory)\n    }\n\n    public async applyEdits(edits: types.WorkspaceEdit): Promise<void> {\n        return null\n    }\n}\n\nexport class MockStatusBarItem implements Oni.StatusBarItem {\n    public show(): void {\n        // tslint:disable-line\n    }\n\n    public hide(): void {\n        // tslint:disable-line\n    }\n\n    public setContents(element: JSX.Element): void {\n        // tslint:disable-line\n    }\n\n    public dispose(): void {\n        // tslint:disable-line\n    }\n}\n\nexport class MockStatusBar implements Oni.StatusBar {\n    public getItem(globalId: string): Oni.StatusBarItem {\n        return new MockStatusBarItem()\n    }\n\n    public createItem(alignment: number, globalId: string): Oni.StatusBarItem {\n        return new MockStatusBarItem()\n    }\n}\n\nexport class MockEditor extends Editor {\n    private _activeBuffer: MockBuffer = null\n    private _currentSelection: types.Range = null\n\n    public init(filesToOpen: string[]): void {\n        throw new Error(\"Not implemented\")\n    }\n\n    public get activeBuffer(): Oni.Buffer {\n        return this._activeBuffer as any\n    }\n\n    public simulateModeChange(newMode: string): void {\n        this.setMode(newMode as any)\n    }\n\n    public simulateCursorMoved(line: number, column: number): void {\n        this.notifyCursorMoved({\n            line,\n            column,\n        })\n    }\n\n    public simulateBufferEnter(buffer: MockBuffer): void {\n        this._activeBuffer = buffer\n        this.notifyBufferEnter(buffer as any)\n    }\n\n    public render(): JSX.Element {\n        throw new Error(\"Not implemented\")\n    }\n\n    public async setSelection(range: types.Range): Promise<void> {\n        this._currentSelection = range\n    }\n\n    public async getSelection(): Promise<types.Range> {\n        return this._currentSelection\n    }\n\n    public async clearSelection(): Promise<void> {\n        // tslint:disable-line\n    }\n\n    public setActiveBufferLine(line: number, lineContents: string): void {\n        this._activeBuffer.setLineSync(line, lineContents)\n\n        this.notifyBufferChanged({\n            buffer: this._activeBuffer as any,\n            contentChanges: [\n                {\n                    range: types.Range.create(line, 0, line + 1, 0),\n                    text: lineContents,\n                },\n            ],\n        })\n    }\n}\n\nconst DefaultCursorMatchRegEx = /[a-z]/i\nconst DefaultTriggerCharacters = [\".\"]\n\nexport class MockLanguageManager {\n    public getTokenRegex(language: string): RegExp {\n        return DefaultCursorMatchRegEx\n    }\n\n    public getCompletionTriggerCharacters(language: string): string[] {\n        return DefaultTriggerCharacters\n    }\n}\n\nexport class MockRequestor<T> {\n    private _completablePromises: Array<ICompletablePromise<T>> = []\n\n    public get pendingCallCount(): number {\n        return this._completablePromises.length\n    }\n\n    public get(...args: any[]): Promise<T> {\n        const newPromise = createCompletablePromise<T>()\n\n        this._completablePromises.push(newPromise)\n\n        return newPromise.promise\n    }\n\n    public resolve(val: T): void {\n        const firstPromise = this._completablePromises.shift()\n        firstPromise.resolve(val)\n    }\n}\n\nexport class MockDefinitionRequestor extends MockRequestor<Language.IDefinitionResult>\n    implements Language.IDefinitionRequestor {\n    public getDefinition(\n        language: string,\n        filePath: string,\n        line: number,\n        column: number,\n    ): Promise<Language.IDefinitionResult> {\n        return this.get(language, filePath, line, column)\n    }\n}\n\nexport class MockHoverRequestor extends MockRequestor<Language.IHoverResult>\n    implements Language.IHoverRequestor {\n    public getHover(\n        language: string,\n        filePath: string,\n        line: number,\n        column: number,\n    ): Promise<Language.IHoverResult> {\n        return this.get(language, filePath, line, column)\n    }\n}\n\nexport class MockOni implements Oni.Plugin.Api {\n    private _editorManager = new EditorManager()\n    private _pluginManager = new MockPluginManager()\n    private _statusBar = new MockStatusBar()\n    private _workspace = new MockWorkspace()\n\n    constructor(private _configuration: Oni.Configuration = new MockConfiguration()) {\n        this._editorManager.setActiveEditor(new MockEditor())\n    }\n\n    get automation(): Oni.Automation.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get colors(): Oni.IColors {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get commands(): Oni.Commands.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get configuration(): Oni.Configuration {\n        return this._configuration\n    }\n\n    get contextMenu(): any /* TODO */ {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get diagnostics(): Oni.Plugin.Diagnostics.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get editors(): Oni.EditorManager {\n        return this._editorManager\n    }\n\n    get filter(): Oni.Menu.IMenuFilters {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get input(): Oni.Input.InputManager {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get language(): any /* TODO */ {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get log(): any /* TODO */ {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get notifications(): Oni.Notifications.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get overlays(): Oni.Overlays.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get plugins(): Oni.IPluginManager {\n        return this._pluginManager\n    }\n\n    get search(): Oni.Search.ISearch {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get sidebar(): Oni.Sidebar.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get ui(): Oni.Ui.IUi {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get menu(): Oni.Menu.Api {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get process(): Oni.Process {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get recorder(): Oni.Recorder {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get snippets(): Oni.Snippets.SnippetManager {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get statusBar(): Oni.StatusBar {\n        return this._statusBar\n    }\n\n    get windows(): Oni.IWindowManager {\n        throw Error(\"Not yet implemented\")\n    }\n\n    get workspace(): Oni.Workspace.Api {\n        return this._workspace\n    }\n\n    public populateQuickFix(entries: Oni.QuickFixEntry[]): void {\n        throw Error(\"Not yet implemented\")\n    }\n}\n"
  },
  {
    "path": "browser/test/Mocks/neovim/MockNeovimInstance.ts",
    "content": "/**\n * Mocks/neovim/MockNeovimInstance.ts\n *\n * Implementations of test mocks and doubles,\n * for Neovim facing classes / interfaces.\n */\n\nimport * as Utility from \"./../../../src/Utility\"\n\nexport interface NeovimRequest {\n    requestName: string\n    args: any[]\n}\n\nexport class MockNeovimInstance {\n    private _requests: NeovimRequest[] = []\n    private _pendingPromises: Array<Utility.ICompletablePromise<any>> = []\n\n    public get onColorsChanged() {\n        return {\n            subscribe: (fn: (args?: any) => any) => fn(),\n        }\n    }\n\n    public request(requestName: string, args: any[]) {\n        this._requests.push({ requestName, args })\n        const promise = Utility.createCompletablePromise()\n        this._pendingPromises.push(promise)\n\n        return promise.promise\n    }\n\n    public getPendingRequests(): NeovimRequest[] {\n        return this._requests\n    }\n\n    public flushFirstRequest(val: any) {\n        const [firstPromise, ...remainingPromises] = this._pendingPromises\n        const [, ...remainingRequests] = this._requests\n\n        firstPromise.resolve(val)\n\n        this._pendingPromises = remainingPromises\n        this._requests = remainingRequests\n    }\n\n    public flushPendingRequests(): void {\n        this._pendingPromises.forEach(p => p.resolve())\n        this._requests = []\n        this._pendingPromises = []\n    }\n}\n"
  },
  {
    "path": "browser/test/Mocks/neovim.ts",
    "content": "/**\n * Mocks/neovim.ts\n *\n * Implementations of test mocks and doubles,\n * for Neovim facing classes / interfaces.\n */\n\nimport * as Neovim from \"./../../src/neovim\"\n\nexport * from \"./neovim/MockNeovimInstance\"\n\nexport class MockScreen implements Neovim.IScreen {\n    public backgroundColor: string\n    public foregroundColor: string\n    public cursorColumn: number = 0\n    public cursorRow: number = 0\n\n    private _cells: { [row: number]: { [col: number]: Neovim.ICell } } = {}\n\n    public get currentBackgroundColor(): string {\n        return null\n    }\n\n    public get currentForegroundColor(): string {\n        return null\n    }\n\n    public get fontFamily(): null | string {\n        return null\n    }\n    public get fontHeightInPixels(): number {\n        return null\n    }\n    public get fontSize(): null | string {\n        return null\n    }\n    public get fontWeight(): null | string {\n        return null\n    }\n    public get fontWidthInPixels(): number {\n        return null\n    }\n    public get height(): number {\n        return null\n    }\n    public get linePaddingInPixels(): number {\n        return null\n    }\n    public get mode(): string {\n        return \"normal\"\n    }\n    public get width(): number {\n        return null\n    }\n\n    public dispatch(action: Neovim.IAction): void {\n        // tslint:disable-line\n    }\n\n    public getCell(x: number, y: number): Neovim.ICell {\n        const row = this._cells[y]\n\n        if (!row) {\n            return null\n        }\n\n        const cell = row[x]\n        return cell || null\n    }\n\n    public setCell(x: number, y: number, cell: Neovim.ICell): void {\n        const row = this._cells[y] || {}\n\n        const updatedRow = {\n            ...row,\n            [x]: cell,\n        }\n\n        this._cells[y] = updatedRow\n    }\n\n    public getScrollRegion(): Neovim.IScrollRegion {\n        return null\n    }\n}\n"
  },
  {
    "path": "browser/test/Plugins/Api/ProcessTests.ts",
    "content": "/**\n * ProcessTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { IShellEnvironmentFetcher, Process } from \"./../../../src/Plugins/Api/Process\"\n\nclass MockShellEnvironmentFetcher implements IShellEnvironmentFetcher {\n    constructor(private _env: any) {}\n\n    public async getEnvironmentVariables(): Promise<any> {\n        return this._env\n    }\n}\n\ndescribe(\"ProcessTests\", () => {\n    it(\"mergeSpawnOptions takes into account shell environment\", async () => {\n        const mockShellEnv = new MockShellEnvironmentFetcher({ test2: true })\n        const process = new Process(mockShellEnv)\n\n        const newOptions = await process.mergeSpawnOptions({\n            env: {\n                test1: true,\n            },\n        })\n\n        assert.strictEqual(newOptions.env.test1, true)\n        assert.strictEqual(newOptions.env.test2, true)\n    })\n})\n"
  },
  {
    "path": "browser/test/Renderer/SpanTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as Span from \"./../../src/Renderer/Span\"\n\ndescribe(\"Span\", () => {\n    describe(\"flattenSpansToArray\", () => {\n        it(\"simple test\", () => {\n            const output = Span.flattenSpansToArray([\n                { startX: 1, endX: 2 },\n                { startX: 3, endX: 5 },\n            ])\n            assert.deepEqual(output, [null, true, false, true, true])\n        })\n    })\n\n    describe(\"expandArrayToSpans\", () => {\n        it(\"simple test\", () => {\n            const input = [{ startX: 1, endX: 2 }, { startX: 3, endX: 5 }]\n            const array = Span.flattenSpansToArray(input)\n            const expanded = Span.expandArrayToSpans(array)\n\n            assert.deepEqual(expanded, input)\n        })\n    })\n\n    describe(\"collapeSpans\", () => {\n        it(\"does not collapse spans that are not adjacent\", () => {\n            const spans = [{ startX: 1, endX: 4 }, { startX: 5, endX: 6 }]\n            const outSpans = Span.collapseSpans(spans)\n\n            assert.deepEqual(outSpans, spans)\n        })\n\n        it(\"does collapse spans that overlap\", () => {\n            const spans = [{ startX: 1, endX: 4 }, { startX: 3, endX: 5 }]\n            const outSpans = Span.collapseSpans(spans)\n\n            assert.deepEqual(outSpans, [{ startX: 1, endX: 5 }])\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/AutoClosingPairsTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as Mocks from \"./../Mocks\"\n\nimport {\n    checkOpenCharacter,\n    getWhiteSpacePrefix,\n    IAutoClosingPair,\n} from \"./../../src/Services/AutoClosingPairs\"\n\ndescribe(\"AutoClosingPairs\", () => {\n    describe(\"getWhitespacePrefix\", () => {\n        it(\"returns empty if the string doesn't have whitespace\", () => {\n            const result = getWhiteSpacePrefix(\"test\")\n            assert.strictEqual(result, \"\")\n        })\n\n        it(\"returns tab\", () => {\n            const result = getWhiteSpacePrefix(\"\\ttest\")\n            assert.strictEqual(result, \"\\t\")\n        })\n\n        it(\"returns spaces\", () => {\n            const result = getWhiteSpacePrefix(\"  test\")\n            assert.strictEqual(result, \"  \")\n        })\n    })\n\n    describe(\"handleOpenCharacter\", () => {\n        let mockEditor: Mocks.MockEditor\n        let mockBuffer: Mocks.MockBuffer\n\n        beforeEach(() => {\n            mockEditor = new Mocks.MockEditor()\n            mockBuffer = new Mocks.MockBuffer(\"typescript\", \"test.ts\", [\"\"])\n            mockEditor.simulateBufferEnter(mockBuffer)\n        })\n\n        it(\"inserts both characters of the pair\", async () => {\n            const pair = { open: \"(\", close: \")\" } as IAutoClosingPair\n\n            mockBuffer.setLinesSync([\"(\"])\n            await checkOpenCharacter(\n                (str: string) => {\n                    mockBuffer.setLinesSync([str])\n                },\n                pair,\n                mockEditor as any,\n                false,\n            )\n\n            const [firstLine] = await mockBuffer.getLines(0, 1)\n\n            assert.strictEqual(firstLine, \"()\")\n        })\n\n        it(\"doesn't duplicate quote on close\", async () => {\n            const pair = { open: '\"', close: '\"' } as IAutoClosingPair\n\n            mockBuffer.setLinesSync(['\"Oni\"'])\n            mockBuffer.setCursorPosition(0, 4)\n            await checkOpenCharacter(\n                (str: string) => {\n                    mockBuffer.setLinesSync([str])\n                },\n                pair,\n                mockEditor as any,\n                true,\n            )\n\n            const [firstLine] = await mockBuffer.getLines(0, 1)\n\n            assert.strictEqual(firstLine, '\"Oni\"')\n        })\n\n        it(\"moves the cursor correctly onto the closing quote\", async () => {\n            const pair = { open: \"'\", close: \"'\" } as IAutoClosingPair\n\n            mockBuffer.setLinesSync([\"'Oni'\"])\n            mockBuffer.setCursorPosition(0, 4)\n\n            await checkOpenCharacter(\n                (str: string) => {\n                    mockBuffer.setLinesSync([str])\n                },\n                pair,\n                mockEditor as any,\n                true,\n            )\n\n            const endCursorPos = await mockBuffer.getCursorPosition()\n            assert.strictEqual(endCursorPos.character, 5)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Completion/CompletionProvidersTests.ts",
    "content": "/**\n * CompletionProvidersTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport {\n    CompletionProviders,\n    CompletionsRequestContext,\n    ICompletionsRequestor,\n} from \"./../../../src/Services/Completion\"\n\nexport class MockCompletionsRequestor implements ICompletionsRequestor {\n    constructor(private _hardcodedCompletions: types.CompletionItem[]) {}\n\n    public async getCompletions(\n        context: CompletionsRequestContext,\n    ): Promise<types.CompletionItem[]> {\n        return this._hardcodedCompletions\n    }\n\n    public async getCompletionDetails(\n        fileLanguage: string,\n        filePath: string,\n        completionItem: types.CompletionItem,\n    ): Promise<types.CompletionItem> {\n        return null\n    }\n}\n\nconst createCompletionItem = (item: string): types.CompletionItem => ({\n    label: item,\n    detail: item,\n})\n\nconst createContext = (language: string, filePath: string, line: number, column: number) => ({\n    language,\n    filePath,\n    line,\n    column,\n    meetCharacter: \"\",\n    textMateScopes: [] as string[],\n})\n\ndescribe(\"CompletionProvider\", () => {\n    it(\"combines completions from multiple providers\", async () => {\n        const provider1 = new MockCompletionsRequestor([\n            createCompletionItem(\"a\"),\n            createCompletionItem(\"b\"),\n        ])\n        const provider2 = new MockCompletionsRequestor([\n            createCompletionItem(\"c\"),\n            createCompletionItem(\"d\"),\n        ])\n\n        const completionProviders = new CompletionProviders()\n        completionProviders.registerCompletionProvider(\"provider1\", provider1)\n        completionProviders.registerCompletionProvider(\"provider2\", provider2)\n\n        const result = await completionProviders.getCompletions(createContext(\"lang\", \"file\", 0, 0))\n\n        const resultItems = result.map(i => i.label)\n\n        assert.strictEqual(result.length, 4)\n        assert.deepEqual(resultItems, [\"a\", \"b\", \"c\", \"d\"])\n    })\n\n    it(\"handles case where one completion provider returns null\", async () => {\n        const provider1 = new MockCompletionsRequestor(null)\n        const provider2 = new MockCompletionsRequestor([\n            createCompletionItem(\"c\"),\n            createCompletionItem(\"d\"),\n        ])\n\n        const completionProviders = new CompletionProviders()\n        completionProviders.registerCompletionProvider(\"provider1\", provider1)\n        completionProviders.registerCompletionProvider(\"provider2\", provider2)\n\n        const result = await completionProviders.getCompletions(createContext(\"lang\", \"file\", 0, 0))\n\n        const resultItems = result.map(i => i.label)\n\n        assert.strictEqual(result.length, 2)\n        assert.deepEqual(resultItems, [\"c\", \"d\"])\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Completion/CompletionSelectorsTests.ts",
    "content": "import * as assert from \"assert\"\nimport { CompletionItem } from \"vscode-languageserver-types\"\n\nimport { filterCompletionOptions } from \"../../../src/Services/Completion/CompletionSelectors\"\n\ndescribe(\"filterCompletionOptions\", () => {\n    it(\"strips duplicates and sorts in order of abbreviation=>label=>sortText\", () => {\n        const item1: CompletionItem = {\n            label: \"mock duplicate\",\n            detail: \"mock detail\",\n            sortText: \"c\",\n        }\n        const item2: CompletionItem = {\n            label: \"mock duplicate\",\n            detail: \"mock detail\",\n            sortText: \"b\",\n        }\n        const item3: CompletionItem = {\n            label: \"mock duplicate\",\n            detail: \"mock not duplicate detail\",\n            sortText: \"a\",\n        }\n        const item4: CompletionItem = {\n            label: \"maaaaoaaaacaaaak abbreviation\",\n        }\n        const item5: CompletionItem = {\n            label: \"mock cherry\",\n            filterText: \"mock cherry\",\n        }\n        const item6: CompletionItem = {\n            label: \"mock cherry\",\n            filterText: \"mock banana\",\n        }\n        const item7: CompletionItem = {\n            label: \"mock apple\",\n        }\n        const item8: CompletionItem = {\n            label: \"doesnt match\",\n        }\n        const item9: CompletionItem = {\n            label: \"mock apple\",\n            filterText: \"doesnt match either\",\n        }\n        const items: CompletionItem[] = [\n            item1,\n            item2,\n            item3,\n            item4,\n            item5,\n            item6,\n            item7,\n            item8,\n            item9,\n        ]\n\n        const filteredItems = filterCompletionOptions(items, \"mock\")\n\n        assert.deepStrictEqual(filteredItems, [item7, item6, item5, item3, item2, item4])\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Completion/CompletionStoreTests.ts",
    "content": "import * as assert from \"assert\"\nimport * as _ from \"lodash\"\n\nimport { DefaultCompletionResults } from \"./../../../src/Services/Completion/CompletionState\"\nimport { completionResultsReducer } from \"./../../../src/Services/Completion/CompletionStore\"\n\ndescribe(\"completionResultsReducer\", () => {\n    let oldState: any\n\n    beforeEach(() => {\n        oldState = _.cloneDeep(DefaultCompletionResults)\n    })\n\n    describe(\"GET_COMPLETION_ITEM_DETAILS_RESULT\", () => {\n        beforeEach(() => {\n            oldState.completions = [\n                { label: \"other\" },\n                { label: \"matchme\", detail: \"matchme(signature)\" },\n                { label: \"matchme\", detail: \"other(signature)\" },\n                { label: \"matchme\" },\n            ]\n        })\n\n        it(\"updates relevant items with detailed version by label field\", () => {\n            const completionItemWithDetails = {\n                label: \"matchme\",\n            }\n\n            const newState = completionResultsReducer(oldState, {\n                type: \"GET_COMPLETION_ITEM_DETAILS_RESULT\",\n                completionItemWithDetails,\n            })\n\n            assert.deepStrictEqual(newState, {\n                ...oldState,\n                completions: [\n                    { label: \"other\" },\n                    completionItemWithDetails,\n                    completionItemWithDetails,\n                    completionItemWithDetails,\n                ],\n            })\n        })\n\n        it(\"updates relevant items with detailed version by detail field\", () => {\n            const completionItemWithDetails = {\n                label: \"matchme\",\n                detail: \"matchme(signature)\",\n            }\n            const newState = completionResultsReducer(oldState, {\n                type: \"GET_COMPLETION_ITEM_DETAILS_RESULT\",\n                completionItemWithDetails,\n            })\n\n            assert.deepStrictEqual(newState, {\n                ...oldState,\n                completions: [\n                    { label: \"other\" },\n                    completionItemWithDetails,\n                    { label: \"matchme\", detail: \"other(signature)\" },\n                    completionItemWithDetails,\n                ],\n            })\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Completion/CompletionTests.ts",
    "content": "/**\n * CompletionTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Completion from \"./../../../src/Services/Completion\"\nimport * as SyntaxHighlighting from \"./../../../src/Services/SyntaxHighlighting\"\n\nimport * as Mocks from \"./../../Mocks\"\nimport * as TestHelpers from \"./../../TestHelpers\"\n\nexport class MockCompletionRequestor implements Completion.ICompletionsRequestor {\n    private _completionsRequestor: Mocks.MockRequestor<\n        types.CompletionItem[]\n    > = new Mocks.MockRequestor<types.CompletionItem[]>()\n    private _completionDetailsRequestor: Mocks.MockRequestor<\n        types.CompletionItem\n    > = new Mocks.MockRequestor<types.CompletionItem>()\n\n    public get completionsRequestor(): Mocks.MockRequestor<types.CompletionItem[]> {\n        return this._completionsRequestor\n    }\n\n    public get completionDetailsRequestor(): Mocks.MockRequestor<types.CompletionItem> {\n        return this._completionDetailsRequestor\n    }\n\n    public getCompletions(\n        context: Completion.CompletionsRequestContext,\n    ): Promise<types.CompletionItem[]> {\n        return this._completionsRequestor.get(\n            context.language,\n            context.filePath,\n            context.line,\n            context.column,\n        )\n    }\n\n    public getCompletionDetails(\n        fileLanguage: string,\n        filePath: string,\n        completionItem: types.CompletionItem,\n    ): Promise<types.CompletionItem> {\n        return this._completionDetailsRequestor.get(fileLanguage, filePath, completionItem)\n    }\n}\n\nconst createMockCompletionItem = (label: string): types.CompletionItem => {\n    const ci: types.CompletionItem = {\n        label,\n        kind: types.CompletionItemKind.Variable,\n    }\n    return ci\n}\n\ndescribe(\"Completion\", () => {\n    // Mocks\n    let mockConfiguration: Mocks.MockConfiguration\n    let mockEditor: Mocks.MockEditor\n    let mockLanguageManager: Mocks.MockLanguageManager\n    let mockCompletionRequestor: MockCompletionRequestor\n\n    // Class under test\n    let completion: Completion.Completion\n\n    beforeEach(() => {\n        mockConfiguration = new Mocks.MockConfiguration({\n            \"editor.completions.mode\": \"oni\",\n        })\n\n        mockEditor = new Mocks.MockEditor()\n        mockLanguageManager = new Mocks.MockLanguageManager()\n        mockCompletionRequestor = new MockCompletionRequestor()\n        completion = new Completion.Completion(\n            mockEditor,\n            mockConfiguration as any,\n            mockCompletionRequestor,\n            mockLanguageManager as any,\n            null /* snippet manager */,\n            new SyntaxHighlighting.NullSyntaxHighlighter(),\n        )\n    })\n\n    afterEach(() => {\n        completion.dispose()\n    })\n\n    it(\"shows completions, filtered by base\", async () => {\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing\n        mockEditor.simulateCursorMoved(0, 1)\n        mockEditor.setActiveBufferLine(0, \"w\")\n\n        TestHelpers.runAllTimers()\n\n        let lastItems: Completion.ICompletionShowEventArgs = null\n        completion.onShowCompletionItems.subscribe(items => (lastItems = items))\n\n        // Validate we have a request for completions\n        assert.strictEqual(\n            mockCompletionRequestor.completionsRequestor.pendingCallCount,\n            1,\n            \"There should be a request for completions queued\",\n        )\n\n        const completionResults = [\n            createMockCompletionItem(\"win\"),\n            createMockCompletionItem(\"window\"),\n        ]\n\n        mockCompletionRequestor.completionsRequestor.resolve(completionResults)\n\n        await TestHelpers.waitForAllAsyncOperations()\n\n        assert.deepEqual(\n            lastItems.filteredCompletions,\n            completionResults,\n            \"There should now be completion results available\",\n        )\n        assert.deepEqual(lastItems.base, \"w\", \"The base should be set correctly\")\n    })\n\n    it(\"doesn't fetch completions if 'editor.completions.mode' === 'hidden'\", () => {\n        mockConfiguration.setValue(\"editor.completions.mode\", \"hidden\")\n\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing\n        mockEditor.simulateCursorMoved(0, 3)\n        mockEditor.setActiveBufferLine(0, \"win\")\n\n        TestHelpers.runAllTimers()\n\n        // Validate we do not have requests for completion, because completions are turned off.\n        assert.strictEqual(\n            mockCompletionRequestor.completionsRequestor.pendingCallCount,\n            0,\n            \"There should be no completion requests, because 'editor.completions.mode' is set to 'hidden'\",\n        )\n    })\n\n    it(\"doesn't fetch completions if 'editor.completions.enabled' === 'false'\", () => {\n        mockConfiguration.setValue(\"editor.completions.enabled\", false)\n\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing\n        mockEditor.simulateCursorMoved(0, 3)\n        mockEditor.setActiveBufferLine(0, \"win\")\n\n        TestHelpers.runAllTimers()\n\n        // Validate we do not have requests for completion, because completions are turned off.\n        assert.strictEqual(\n            mockCompletionRequestor.completionsRequestor.pendingCallCount,\n            0,\n            \"There should be no completion requests, because 'editor.completions.enabled' is set to 'false'\",\n        )\n    })\n\n    it(\"if there is a completion matching the base, it should be the first shown\", async () => {\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing\n        mockEditor.simulateCursorMoved(0, 3)\n        mockEditor.setActiveBufferLine(0, \"win\")\n\n        TestHelpers.runAllTimers()\n\n        let lastItems: Completion.ICompletionShowEventArgs = null\n        completion.onShowCompletionItems.subscribe(items => (lastItems = items))\n\n        // Validate we have a request for completions\n        assert.strictEqual(\n            mockCompletionRequestor.completionsRequestor.pendingCallCount,\n            1,\n            \"There should be a request for completions queued\",\n        )\n\n        const completionResults = [\n            createMockCompletionItem(\"window\"),\n            createMockCompletionItem(\"win\"),\n        ]\n\n        mockCompletionRequestor.completionsRequestor.resolve(completionResults)\n\n        await TestHelpers.waitForAllAsyncOperations()\n\n        assert.strictEqual(\n            lastItems.filteredCompletions.length,\n            2,\n            \"Completions were resolved successfully\",\n        )\n        assert.deepEqual(\n            lastItems.filteredCompletions[0],\n            completionResults[1],\n            \"The second completion should be the first one shown, as it matches the base\",\n        )\n    })\n\n    it(\"if mode changed while a request was in progress, there should be no completions shown\", async () => {\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing\n        mockEditor.simulateCursorMoved(0, 3)\n        mockEditor.setActiveBufferLine(0, \"win\")\n\n        TestHelpers.runAllTimers()\n\n        let lastItems: Completion.ICompletionShowEventArgs = null\n        completion.onShowCompletionItems.subscribe(items => (lastItems = items))\n\n        // Validate we have a request for completions\n        assert.strictEqual(\n            mockCompletionRequestor.completionsRequestor.pendingCallCount,\n            1,\n            \"There should be a request for completions queued\",\n        )\n\n        // While the result is pending, we'll leave insert mode -\n        // we shouldn't get any completions, now!\n\n        mockEditor.simulateModeChange(\"normal\")\n\n        TestHelpers.runAllTimers()\n\n        // Resolve the slow request...\n        const completionResults = [\n            createMockCompletionItem(\"window\"),\n            createMockCompletionItem(\"win\"),\n        ]\n\n        mockCompletionRequestor.completionsRequestor.resolve(completionResults)\n\n        await TestHelpers.waitForAllAsyncOperations()\n\n        assert.strictEqual(\n            lastItems,\n            null,\n            \"Completions should be null, as we shouldn't have received them after the mode change\",\n        )\n    })\n\n    it(\"if meet changed while the request was in progress, there should be no completions shown\", async () => {\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing\n        mockEditor.simulateCursorMoved(0, 3)\n        mockEditor.setActiveBufferLine(0, \"win\")\n\n        TestHelpers.runAllTimers()\n\n        let lastItems: Completion.ICompletionShowEventArgs = null\n        completion.onShowCompletionItems.subscribe(items => (lastItems = items))\n\n        // Validate we have a request for completions\n        assert.strictEqual(\n            mockCompletionRequestor.completionsRequestor.pendingCallCount,\n            1,\n            \"There should be a request for completions queued\",\n        )\n\n        // While the result is pending, we'll keep typing...\n        // That first result should be ignored\n\n        mockEditor.simulateCursorMoved(0, 5)\n        mockEditor.setActiveBufferLine(0, \"win.s\")\n\n        TestHelpers.runAllTimers()\n\n        // Resolve the slow request...\n        const oldCompletionResults = [\n            createMockCompletionItem(\"window\"),\n            createMockCompletionItem(\"win\"),\n        ]\n\n        mockCompletionRequestor.completionsRequestor.resolve(oldCompletionResults)\n\n        await TestHelpers.waitForAllAsyncOperations()\n\n        assert.strictEqual(\n            lastItems,\n            null,\n            \"Completions should be null, as the only request that was completed was outdated\",\n        )\n    })\n\n    it(\"#1076 - should not crash if buffer change comes before first cursor move\", () => {\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer(\"typescript\", \"test1.ts\", []))\n\n        // Switch to insert mode\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Simulate typing, but with the buffer update coming prior to the cursor move.\n        mockEditor.setActiveBufferLine(0, \"win\")\n        mockEditor.simulateCursorMoved(0, 3)\n\n        assert.ok(true, \"Did not crash\")\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Completion/CompletionUtilityTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as CompletionUtility from \"./../../../src/Services/Completion/CompletionUtility\"\nimport { EditorManager } from \"./../../../src/Services/EditorManager\"\nimport { SnippetManager } from \"./../../../src/Services/Snippets\"\n\nconst DefaultCursorMatchRegEx = /[a-z]/i\nconst DefaultTriggerCharacters = [\".\"]\n\nimport { MockBuffer, MockConfiguration, MockEditor } from \"./../../Mocks\"\n\ndescribe(\"CompletionUtility\", () => {\n    describe(\"commitCompletion\", () => {\n        let mockConfiguration: MockConfiguration\n        let editorManager: EditorManager\n        let mockEditor: MockEditor\n        let snippetManager: SnippetManager\n\n        beforeEach(() => {\n            editorManager = new EditorManager()\n            mockEditor = new MockEditor()\n            editorManager.setActiveEditor(mockEditor)\n            mockConfiguration = new MockConfiguration({})\n            snippetManager = new SnippetManager(mockConfiguration as any, editorManager)\n        })\n\n        it(\"handles basic completion\", async () => {\n            const mockBuffer = new MockBuffer()\n            mockBuffer.setLinesSync([\"some comp sentence\"])\n            mockBuffer.setCursorPosition(0, 9)\n\n            const simpleCompletionItem = types.CompletionItem.create(\"completion\")\n            simpleCompletionItem.insertText = \"completion\"\n\n            await CompletionUtility.commitCompletion(mockBuffer as any, 0, 5, simpleCompletionItem)\n\n            const [resultLine] = await mockBuffer.getLines(0, 1)\n\n            assert.strictEqual(resultLine, \"some completion sentence\")\n        })\n\n        it(\"inserts a snippet\", async () => {\n            const mockBuffer = new MockBuffer()\n            mockEditor.simulateBufferEnter(mockBuffer)\n            mockBuffer.setLinesSync([\"some comp sentence\"])\n            mockBuffer.setCursorPosition(0, 9)\n\n            const snippetCompletionItem = types.CompletionItem.create(\"completion_snippet\")\n            snippetCompletionItem.insertText = \"${0:foo} ${1:bar}\" // tslint:disable-line\n            snippetCompletionItem.insertTextFormat = types.InsertTextFormat.Snippet\n\n            await CompletionUtility.commitCompletion(\n                mockBuffer as any,\n                0,\n                5,\n                snippetCompletionItem,\n                snippetManager,\n            )\n\n            const [resultLine] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(resultLine, \"some foo bar sentence\")\n        })\n    })\n\n    describe(\"getCompletionStart\", () => {\n        it(\"rewinds back to first character\", () => {\n            const bufferLine = \"abc\"\n            const cursorColumn = 5\n            const completion = \"c\"\n\n            const completionStart = CompletionUtility.getCompletionStart(\n                bufferLine,\n                cursorColumn,\n                completion,\n            )\n            assert.strictEqual(completionStart, 2)\n        })\n    })\n\n    describe(\"getCompletionMeet\", () => {\n        it(\"shouldExpandCompletions is true when at end of word\", () => {\n            const line = \"const\"\n            const cursorPosition = 5 // const|\n\n            const meet = CompletionUtility.getCompletionMeet(\n                line,\n                cursorPosition,\n                DefaultCursorMatchRegEx,\n                DefaultTriggerCharacters,\n            )\n\n            const expectedResult = {\n                position: 0,\n                positionToQuery: 1, // When there is no trigger character, we expect it to be an extra position forward\n                base: \"const\",\n                shouldExpandCompletions: true,\n            }\n\n            assert.deepEqual(meet, expectedResult)\n        })\n\n        it(\"shouldExpandCompletions is false when in the middle of a word\", () => {\n            const line = \"const\"\n            const cursorPosition = 3 // con|st\n\n            const meet = CompletionUtility.getCompletionMeet(\n                line,\n                cursorPosition,\n                DefaultCursorMatchRegEx,\n                DefaultTriggerCharacters,\n            )\n\n            const expectedResult = {\n                position: 0,\n                positionToQuery: 1, // When there is no trigger character, we expect it to be an extra position forward\n                base: \"con\",\n                shouldExpandCompletions: false,\n            }\n\n            assert.deepEqual(meet, expectedResult)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Completion/CompletionsRequestorTests.ts",
    "content": "import * as assert from \"assert\"\nimport * as sinon from \"sinon\"\n\nimport { LanguageServiceCompletionsRequestor } from \"./../../../src/Services/Completion/CompletionsRequestor\"\nimport { LanguageManager } from \"./../../../src/Services/Language\"\n\ndescribe(\"LanguageServiceCompletionsRequestor\", () => {\n    describe(\"getCompletionDetails\", () => {\n        let completionItem: any\n        let completionDetails: any\n        let languageManager: any\n        let requestor: any\n\n        beforeEach(() => {\n            completionItem = sinon.stub()\n            completionDetails = sinon.stub()\n            languageManager = sinon.createStubInstance(LanguageManager)\n            languageManager.sendLanguageServerRequest.resolves(completionDetails)\n            requestor = new LanguageServiceCompletionsRequestor(languageManager)\n        })\n\n        it(\"doesn't send the request if the server is incapable\", async () => {\n            languageManager.getCapabilitiesForLanguage.resolves({\n                completionProvider: { resolveProvider: false },\n            })\n\n            const returnedDetails = await requestor.getCompletionDetails(\n                \"mocklang\",\n                \"mockpath\",\n                completionItem as any,\n            )\n\n            sinon.assert.calledWithExactly(languageManager.getCapabilitiesForLanguage, \"mocklang\")\n            sinon.assert.notCalled(languageManager.sendLanguageServerRequest)\n            assert.strictEqual(returnedDetails, completionItem)\n        })\n\n        it(\"requests completion details if server is capable\", async () => {\n            languageManager.getCapabilitiesForLanguage.resolves({\n                completionProvider: { resolveProvider: true },\n            })\n\n            const returnedDetails = await requestor.getCompletionDetails(\n                \"mocklang\",\n                \"mockpath\",\n                completionItem as any,\n            )\n\n            sinon.assert.calledWithExactly(languageManager.getCapabilitiesForLanguage, \"mocklang\")\n            sinon.assert.calledWithExactly(\n                languageManager.sendLanguageServerRequest,\n                \"mocklang\",\n                \"mockpath\",\n                \"completionItem/resolve\",\n                completionItem,\n            )\n            assert.strictEqual(returnedDetails, completionDetails)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Configuration/ConfigurationTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport {\n    Configuration,\n    GenericConfigurationValues,\n    IConfigurationProvider,\n    IPersistedConfiguration,\n} from \"./../../../src/Services/Configuration\"\n\ndescribe(\"Configuration\", () => {\n    it(\"has default configuration values set on instantiation\", () => {\n        const configuration = new Configuration({ \"test.config\": 1 })\n\n        assert.strictEqual(configuration.getValue(\"test.config\"), 1)\n    })\n\n    it(\"has default values overridden by provider\", () => {\n        const configuration = new Configuration({ \"test.config\": 1 })\n\n        const configProvider = new MockConfigurationProvider({ \"test.config\": 2 })\n\n        configuration.addConfigurationProvider(configProvider)\n\n        assert.strictEqual(configuration.getValue(\"test.config\"), 2)\n    })\n\n    it(\"triggers error event when provider has an error\", () => {\n        const configuration = new Configuration({})\n\n        const errors: Error[] = []\n        configuration.onConfigurationError.subscribe(err => {\n            errors.push(err)\n        })\n\n        const configProvider = new MockConfigurationProvider({})\n\n        configuration.addConfigurationProvider(configProvider)\n        configProvider.simulateError(new Error(\"test error\"))\n\n        assert.strictEqual(errors.length, 1, \"Validate an error was captured\")\n    })\n\n    it(\"triggers change event when provider has an update\", () => {\n        const configuration = new Configuration({ \"test.config\": 1 })\n\n        const configProvider = new MockConfigurationProvider({ \"test.config\": 2 })\n        configuration.addConfigurationProvider(configProvider)\n\n        let hitCount = 0\n        configuration.onConfigurationChanged.subscribe(() => {\n            hitCount++\n        })\n\n        configProvider.simulateConfigChange({ \"test.config\": 3 })\n\n        assert.strictEqual(hitCount, 1, \"Validate 'onConfigurationChanged' was dispatched\")\n        assert.strictEqual(\n            configuration.getValue(\"test.config\"),\n            3,\n            \"Validate configuration was updated\",\n        )\n    })\n\n    it(\"triggers updated event with requireReload true\", () => {\n        const configuration = new Configuration({ \"test.config\": 1 })\n        let hitCount = 0\n\n        configuration.onConfigurationUpdated.subscribe(evt => {\n            hitCount++\n            assert.strictEqual(evt.requiresReload, true, \"Validate requiresReload is set to true\")\n        })\n\n        configuration.setValue(\"test.config\", 2)\n\n        assert.strictEqual(hitCount, 1, \"Validate event handler was triggered\")\n    })\n\n    describe(\"removeConfigurationProvider\", () => {\n        it(\"removes configuration value supplied by provider\", () => {\n            const configuration = new Configuration({ \"test.config\": 1 })\n\n            const configProvider = new MockConfigurationProvider({ \"test.config\": 2 })\n            configuration.addConfigurationProvider(configProvider)\n            configuration.removeConfigurationProvider(configProvider)\n\n            assert.strictEqual(\n                configuration.getValue(\"test.config\"),\n                1,\n                \"Value should now be 1 since the provider was removed\",\n            )\n        })\n\n        it(\"doesn't listen to events from removed provider\", () => {\n            const configuration = new Configuration({ \"test.config\": 1 })\n\n            const configProvider = new MockConfigurationProvider({ \"test.config\": 2 })\n            configuration.addConfigurationProvider(configProvider)\n\n            let changeHitCount = 0\n            let errorHitCount = 0\n\n            configuration.onConfigurationChanged.subscribe(() => changeHitCount++)\n            configuration.onConfigurationError.subscribe(() => errorHitCount++)\n\n            configuration.removeConfigurationProvider(configProvider)\n\n            assert.strictEqual(\n                changeHitCount,\n                1,\n                \"Should've been one change when applying settings after remove\",\n            )\n\n            configProvider.simulateConfigChange({ \"test.config\": 3 })\n            assert.strictEqual(\n                changeHitCount,\n                1,\n                \"Validate change hit count is still 1, since we shouldn't be listening to the removed config provider\",\n            )\n            assert.strictEqual(\n                configuration.getValue(\"test.config\"),\n                1,\n                \"Validate the value is still at 1\",\n            )\n\n            configProvider.simulateError(new Error(\"some error\"))\n            assert.strictEqual(\n                errorHitCount,\n                0,\n                \"Validate there was no event triggered for the removed providers error event\",\n            )\n        })\n    })\n\n    describe(\"registerSetting\", () => {\n        it(\"sets default value\", () => {\n            const configuration = new Configuration()\n            configuration.registerSetting(\"test.setting\", {\n                defaultValue: 1,\n            })\n\n            const val = configuration.getValue(\"test.setting\")\n            assert.strictEqual(val, 1, \"Validate default value gets set\")\n        })\n\n        it(\"default value doesn't override set value\", () => {\n            const configuration = new Configuration()\n\n            configuration.setValue(\"test.setting\", 1)\n\n            configuration.registerSetting(\"test.setting\", {\n                defaultValue: 2,\n            })\n\n            const val = configuration.getValue(\"test.setting\")\n            assert.strictEqual(\n                val,\n                1,\n                \"Validate value is 1, because it shouldn't be overwritten by the default\",\n            )\n        })\n\n        it(\"notifies when value is changed\", () => {\n            const configuration = new Configuration()\n            const setting = configuration.registerSetting(\"test.setting\", {\n                defaultValue: 1,\n            })\n\n            let val: number = null\n            let oldVal: number = null\n            setting.onValueChanged.subscribe(evt => {\n                val = evt.newValue\n                oldVal = evt.oldValue\n            })\n\n            configuration.setValue(\"test.setting\", 2)\n            assert.strictEqual(val, 2, \"Validate new value was populated in event handler\")\n            assert.strictEqual(oldVal, 1, \"Validate the oldValue was set correctly\")\n        })\n\n        it(\"disposed setting no longer receives notifications\", () => {\n            const configuration = new Configuration()\n            const setting = configuration.registerSetting(\"test.setting\", {\n                defaultValue: 1,\n            })\n\n            let hitCount = 0\n            setting.onValueChanged.subscribe(() => {\n                hitCount++\n            })\n\n            setting.dispose()\n            configuration.setValue(\"test.setting\", 2)\n\n            assert.strictEqual(hitCount, 0, \"Event should not have been fired\")\n        })\n\n        it(\"setting metadata is available via the getMetadata call\", () => {\n            const configuration = new Configuration()\n            configuration.registerSetting(\"test.setting\", {\n                description: \"test\",\n                defaultValue: 1,\n            })\n\n            const metadata = configuration.getMetadata(\"test.setting\")\n            assert.strictEqual(metadata.description, \"test\")\n        })\n\n        // TODO:\n        // it(\"applies merge strategy\", () => {\n        //     const configuration = new Configuration()\n\n        //     configuration.registerSetting<string>(\"test.config\", {\n        //         defaultValue: \"\",\n        //         mergeStrategy: (high, low) => high + low\n        //     })\n\n        //     const lowPriorityProvider = new MockConfigurationProvider({ \"test.config\": \"a\" })\n        //     const highPriorityProvider = new  MockConfigurationProvider({\"test.config\": \"b\"})\n\n        //     configuration.addConfigurationProvider(lowPriorityProvider)\n        //     configuration.addConfigurationProvider(highPriorityProvider)\n\n        //     const val = configuration.getValue(\"test.config\")\n        //     assert.strictEqual(val, \"ba\", \"Validate merge strategy is executed\")\n        // })\n    })\n\n    describe(\"persisted configuration\", () => {\n        let persistedConfiguration: IPersistedConfiguration\n\n        beforeEach(() => {\n            persistedConfiguration = new MockPersistedConfiguration()\n        })\n\n        it(\"reads persisted values\", () => {\n            persistedConfiguration.setPersistedValues({\n                \"test.config\": 2,\n            })\n            const configuration = new Configuration({ \"test.config\": 1 }, persistedConfiguration)\n            assert.strictEqual(\n                configuration.getValue(\"test.config\"),\n                2,\n                \"Validate persisted configuration value is read\",\n            )\n        })\n\n        it(\"are overwritten by explicitly set configuration values\", () => {\n            persistedConfiguration.setPersistedValues({\n                \"test.config\": 2,\n            })\n\n            const configProvider = new MockConfigurationProvider({ \"test.config\": 3 })\n\n            const configuration = new Configuration({ \"test.config\": 1 }, persistedConfiguration)\n            configuration.addConfigurationProvider(configProvider)\n            assert.strictEqual(\n                configuration.getValue(\"test.config\"),\n                3,\n                \"Validate persisted configuration is overwrittten by explicitly set configuration\",\n            )\n        })\n\n        it(\"doesn't set values when 'persist' argument is false\", () => {\n            persistedConfiguration.setPersistedValues({\n                \"test.config\": 1,\n            })\n\n            const configuration = new Configuration({ \"test.config\": 1 }, persistedConfiguration)\n\n            configuration.setValues({ \"test.config\": 2 }, false)\n\n            assert.deepEqual(\n                persistedConfiguration.getPersistedValues(),\n                {\n                    \"test.config\": 1,\n                },\n                \"Validate persisted configuration wasn't overwritten since persist was false\",\n            )\n        })\n\n        it(\"does set values when 'persist' argument is true\", () => {\n            const configuration = new Configuration({ \"test.config\": 1 }, persistedConfiguration)\n\n            configuration.setValues({ \"test.config\": 2 }, true)\n\n            assert.deepEqual(\n                persistedConfiguration.getPersistedValues(),\n                {\n                    \"test.config\": 2,\n                },\n                \"Validate persisted configuration was overwritten since persist was true\",\n            )\n        })\n    })\n})\n\nexport class MockPersistedConfiguration implements IPersistedConfiguration {\n    private _values: GenericConfigurationValues = {}\n\n    public getPersistedValues(): GenericConfigurationValues {\n        return this._values\n    }\n\n    public setPersistedValues(configurationValues: GenericConfigurationValues): void {\n        this._values = configurationValues\n    }\n}\n\nexport class MockConfigurationProvider implements IConfigurationProvider {\n    private _onConfigurationChangedEvent = new Event<void>()\n    private _onConfigurationErrorEvent = new Event<Error>()\n\n    private _values: GenericConfigurationValues = {}\n    private _lastError: Error | null = null\n\n    public get onConfigurationChanged(): IEvent<void> {\n        return this._onConfigurationChangedEvent\n    }\n\n    public get onConfigurationError(): IEvent<Error> {\n        return this._onConfigurationErrorEvent\n    }\n\n    constructor(initialValues: GenericConfigurationValues) {\n        this._values = initialValues\n    }\n\n    public getValues(): GenericConfigurationValues {\n        return this._values\n    }\n\n    public getLastError(): Error | null {\n        return this._lastError\n    }\n\n    public activate(api: Oni.Plugin.Api): void {\n        // tslint:disable-line\n    }\n\n    public deactivate(): void {\n        // tslint:disable-line\n    }\n\n    public simulateConfigChange(newValues: GenericConfigurationValues): void {\n        this._values = newValues\n        this._onConfigurationChangedEvent.dispatch()\n    }\n\n    public simulateError(err: Error): void {\n        this._lastError = err\n        this._onConfigurationErrorEvent.dispatch(err)\n    }\n}\n"
  },
  {
    "path": "browser/test/Services/Configuration/FileConfigurationProviderTests.ts",
    "content": "/**\n * FileConfigurationProviderTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { promoteConfigurationToRootLevel } from \"./../../../src/Services/Configuration/FileConfigurationProvider\"\n\ndescribe(\"FileConfigurationProviderTests\", () => {\n    describe(\"promoteConfigurationToRootLevel\", () => {\n        it(\"passes through configuration if no configuration object\", async () => {\n            const val = promoteConfigurationToRootLevel({\n                test1: 1,\n            })\n\n            assert.deepEqual(val, { test1: 1 })\n        })\n\n        it(\"promotes configuration object\", async () => {\n            const val = promoteConfigurationToRootLevel({\n                test1: 1,\n                configuration: {\n                    test2: 2,\n                },\n            })\n\n            assert.deepEqual(val, { test1: 1, test2: 2 })\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Explorer/ExplorerFileSystemTests.ts",
    "content": "import * as assert from \"assert\"\nimport { emptyDir, mkdirp, pathExists, remove, stat, writeFile } from \"fs-extra\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport { FileSystem, OniFileSystem } from \"./../../../src/Services/Explorer/ExplorerFileSystem\"\n\ndescribe(\"File System tests\", async () => {\n    let rootPath: string\n    let filePath: string\n    let secondPath: string\n    let fileSystem: FileSystem\n\n    before(async () => {\n        rootPath = path.normalize(path.join(os.tmpdir(), \"a\", \"test\", \"dir\"))\n        filePath = path.join(rootPath, \"file.txt\")\n        secondPath = path.join(rootPath, \"file1.txt\")\n        await mkdirp(rootPath)\n        fileSystem = OniFileSystem\n    })\n\n    beforeEach(async () => {\n        await Promise.all([\n            emptyDir(fileSystem.backupDir),\n            writeFile(filePath, \"hello world\"),\n            writeFile(secondPath, \"file1.txt\"),\n        ])\n    })\n\n    after(async () => {\n        await remove(rootPath)\n    })\n\n    it(\"Should return false is the file is too big to persist\", async () => {\n        const canPersist = await fileSystem.canPersistNode(filePath, 1)\n        assert.ok(!canPersist)\n    })\n    it(\"Should return true is the file can be persisted\", async () => {\n        const canPersist = await fileSystem.canPersistNode(filePath, 1000)\n        assert.ok(canPersist)\n    })\n    it(\"Should delete the file\", async () => {\n        await fileSystem.deleteNode(secondPath)\n        try {\n            await stat(secondPath)\n        } catch (e) {\n            assert.ok(e.message.includes(\"ENOENT\"))\n        }\n    })\n\n    it(\"Should persist the file\", async () => {\n        await fileSystem.persistNode(secondPath)\n        const stats = await stat(path.join(fileSystem.backupDir, \"file1.txt\"))\n        assert.ok(stats.isFile())\n    })\n\n    it(\"Should move a collection of files to the correct directory\", async () => {\n        const locationOne = path.join(fileSystem.backupDir, \"file.txt\")\n        const locationTwo = path.join(fileSystem.backupDir, \"file1.txt\")\n        const nodes = [\n            { source: locationOne, destination: filePath },\n            { source: locationTwo, destination: secondPath },\n        ]\n        await fileSystem.moveNodesBack(nodes)\n        const firstStats = await stat(locationOne)\n        const secondStats = await stat(locationTwo)\n        assert.ok(firstStats.isFile())\n        assert.ok(secondStats.isFile())\n    })\n\n    it(\"Should create a new file\", async () => {\n        const newPath = path.join(rootPath, \"created.txt\")\n        await fileSystem.writeFile(newPath)\n        const created = await pathExists(newPath)\n        assert.ok(created)\n    })\n\n    it(\"Should throw an error if the filepath already exists\", async () => {\n        try {\n            await fileSystem.writeFile(filePath)\n        } catch (e) {\n            assert.ok(!!e)\n            assert.ok(e.message === \"This path already exists\")\n        }\n    })\n\n    it(\"Should create a new folder\", async () => {\n        const newPath = path.join(rootPath, \"new_dir\")\n        await fileSystem.writeFile(newPath)\n        const created = await pathExists(newPath)\n        assert.ok(created)\n    })\n\n    it(\"Should throw an error if the folderpath already exists\", async () => {\n        try {\n            await fileSystem.mkdir(rootPath)\n        } catch (e) {\n            assert.ok(!!e)\n            assert.ok(e.message === \"This path already exists\")\n        }\n    })\n})\n\ndescribe(\"readdir\", () => {\n    it(\"should not error if directory contains a broken symlink\", async () => {\n        const goodDir = path.join(\"fake_dir\", \"good_dir\")\n        const goodFile = path.join(\"fake_dir\", \"good_file\")\n        const badFile = path.join(\"fake_dir\", \"bad_file\")\n\n        const fileSystem = new FileSystem({\n            readdir(dirPath: string, callback: (err?: Error, result?: string[]) => void) {\n                assert.strictEqual(dirPath, \"fake_dir\")\n                callback(null, [\"good_dir\", \"good_file\", \"bad_file\"])\n            },\n            stat(targetPath: string, callback: (err?: Error, result?: any) => void) {\n                switch (targetPath) {\n                    case goodDir:\n                        return callback(null, {\n                            isDirectory() {\n                                return true\n                            },\n                        })\n                    case goodFile:\n                        return callback(null, {\n                            isDirectory() {\n                                return false\n                            },\n                        })\n                    default:\n                        // On Linux at least, an fs.stat call to a missing file and a broken symlink both result in this error:\n                        return callback(\n                            new Error(`ENOENT: no such file or directory, stat ${targetPath}`),\n                        )\n                }\n            },\n            exists(targetPath: string, callback: any) {\n                assert.fail(\"Should not be used\")\n            },\n            realpath(targetPath: string) {\n                assert.fail(\"Should not be used\")\n            },\n        } as any)\n\n        const expected = [\n            {\n                type: \"folder\",\n                fullPath: goodDir,\n            },\n            {\n                type: \"file\",\n                fullPath: goodFile,\n            },\n            {\n                type: \"file\",\n                fullPath: badFile,\n            },\n        ]\n        const result = await fileSystem.readdir(\"fake_dir\")\n        assert.deepEqual(result, expected)\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Explorer/ExplorerSelectorsTests.ts",
    "content": "/**\n * ExplorerSelectorsTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as ExplorerSelectors from \"./../../../src/Services/Explorer/ExplorerSelectors\"\nimport * as ExplorerState from \"./../../../src/Services/Explorer/ExplorerStore\"\n\nconst createTestFile = (filePath: string): ExplorerState.IFileState => ({\n    type: \"file\",\n    fullPath: filePath,\n})\n\ndescribe(\"ExplorerSelectors\", () => {\n    describe(\"flattenFolderTree\", () => {\n        it(\"flattens a single file\", () => {\n            const file: ExplorerState.IFileState = createTestFile(\"/test/files/testFile.txt\")\n\n            const result = ExplorerSelectors.flattenFolderTree(file, [], {}, 1)\n\n            const expectedResult = [\n                {\n                    id: \"explorer:/test/files/testFile.txt\",\n                    type: \"file\",\n                    filePath: \"/test/files/testFile.txt\",\n                    name: \"testFile.txt\",\n                    modified: false,\n                    indentationLevel: 1,\n                },\n            ]\n\n            assert.deepEqual(result, expectedResult)\n        })\n\n        it(\"flattens a single folder\", () => {\n            const folder: ExplorerState.IFolderState = {\n                type: \"folder\",\n                fullPath: \"/test/folder/folderPath\",\n            }\n\n            const result = ExplorerSelectors.flattenFolderTree(folder, [], {}, 1)\n\n            const expectedResult = [\n                {\n                    type: \"folder\",\n                    id: \"explorer:/test/folder/folderPath\",\n                    folderPath: \"/test/folder/folderPath\",\n                    name: \"folderPath\",\n                    expanded: false,\n                    indentationLevel: 1,\n                },\n            ]\n\n            assert.deepEqual(result, expectedResult)\n        })\n\n        it(\"flattens a folder with subfiles\", () => {\n            const folder: ExplorerState.IFolderState = {\n                type: \"folder\",\n                fullPath: \"/test/folder1/folderPath\",\n            }\n\n            const expandedFolders = {\n                \"/test/folder1/folderPath\": [createTestFile(\"/test/files/file1\")],\n            }\n\n            const result = ExplorerSelectors.flattenFolderTree(folder, [], expandedFolders, 1)\n\n            const expectedResult = [\n                {\n                    type: \"folder\",\n                    id: \"explorer:/test/folder1/folderPath\",\n                    folderPath: \"/test/folder1/folderPath\",\n                    name: \"folderPath\",\n                    expanded: true,\n                    indentationLevel: 1,\n                },\n                {\n                    type: \"file\",\n                    id: \"explorer:/test/files/file1\",\n                    filePath: \"/test/files/file1\",\n                    name: \"file1\",\n                    modified: false,\n                    indentationLevel: 2,\n                },\n            ]\n\n            assert.deepEqual(result, expectedResult)\n        })\n    })\n\n    describe(\"mapStateToNodeList\", () => {\n        it(\"expands the root container\", () => {\n            const state: ExplorerState.IExplorerState = {\n                ...ExplorerState.DefaultExplorerState,\n                rootFolder: {\n                    type: \"folder\",\n                    fullPath: \"rootPath\",\n                },\n                expandedFolders: {\n                    rootPath: [],\n                },\n            }\n\n            const result = ExplorerSelectors.mapStateToNodeList(state)\n\n            const container = result[0] as ExplorerSelectors.IContainerNode\n            assert.strictEqual(container.type, \"container\")\n            assert.strictEqual(container.expanded, true)\n        })\n\n        it(\"collapses the root container\", () => {\n            const state: ExplorerState.IExplorerState = {\n                ...ExplorerState.DefaultExplorerState,\n                rootFolder: {\n                    type: \"folder\",\n                    fullPath: \"rootPath\",\n                },\n                expandedFolders: {},\n            }\n            const result = ExplorerSelectors.mapStateToNodeList(state)\n\n            const container = result[0] as ExplorerSelectors.IContainerNode\n            assert.strictEqual(container.type, \"container\")\n            assert.strictEqual(container.expanded, false)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Explorer/ExplorerStoreTests.ts",
    "content": "/**\n * ExplorerStoreTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as path from \"path\"\n\nimport { Store } from \"redux\"\nimport configureMockStore, { MockStoreCreator } from \"redux-mock-store\"\nimport { ActionsObservable, combineEpics, createEpicMiddleware } from \"redux-observable\"\nimport * as sinon from \"sinon\"\n\nimport * as ExplorerFileSystem from \"./../../../src/Services/Explorer/ExplorerFileSystem\"\nimport { ExplorerNode } from \"./../../../src/Services/Explorer/ExplorerSelectors\"\nimport * as ExplorerState from \"./../../../src/Services/Explorer/ExplorerStore\"\nimport { Notification } from \"./../../../src/Services/Notifications/Notification\"\nimport { Notifications } from \"./../../../src/Services/Notifications/Notifications\"\n\nimport * as clone from \"lodash/clone\"\nimport * as head from \"lodash/head\"\nimport * as TestHelpers from \"./../../TestHelpers\"\n\nconst MemoryFileSystem = require(\"memory-fs\") // tslint:disable-line\n// Monkey patch realpath since it doesn't exist in memory-fs.\nMemoryFileSystem.prototype.realpath = (\n    fullPath: string,\n    callback: (err: any, fullPath: string) => void,\n) => {\n    callback(null, fullPath)\n}\n\nexport class MockedFileSystem implements ExplorerFileSystem.IFileSystem {\n    public promises: Array<Promise<any>>\n\n    constructor(private _inner: ExplorerFileSystem.IFileSystem) {\n        this.promises = []\n    }\n\n    public readdir(directoryPath: string): Promise<ExplorerState.FolderOrFile[]> {\n        const promise = this._inner.readdir(directoryPath)\n        this.promises.push(promise)\n        return promise\n    }\n\n    public exists(fullPath: string): Promise<boolean> {\n        const promise = this._inner.exists(fullPath)\n        this.promises.push(promise)\n        return promise\n    }\n\n    public realpath(fullPath: string): Promise<string> {\n        const promise = this._inner.realpath(fullPath)\n        this.promises.push(promise)\n        return promise\n    }\n\n    public async canPersistNode() {\n        return true\n    }\n\n    // tslint:disable\n    public async restoreNode() {}\n    public async persistNode() {}\n    public async moveNodesBack(): Promise<void> {}\n    public async deleteNode(): Promise<void> {}\n    public async move(source: string, destination: string): Promise<void> {}\n    public async writeFile(name: string): Promise<void> {}\n    public async mkdir(name: string): Promise<void> {}\n    // tslint:enable\n}\n\nconst mockFileSystem = (): MockedFileSystem => {\n    const memoryFileSystem = new MemoryFileSystem()\n    const fileSystem = new MockedFileSystem(\n        new ExplorerFileSystem.FileSystem(memoryFileSystem as any),\n    )\n    return fileSystem\n}\n\nconst mockStoreFactory = (\n    epics: any[],\n    notifications = {} as Notifications,\n    fileSystem: ExplorerFileSystem.IFileSystem = mockFileSystem(),\n): MockStoreCreator<ExplorerState.IExplorerState> => {\n    const rootEpic = combineEpics(...epics)\n\n    const epicMiddleware = createEpicMiddleware(rootEpic, {\n        dependencies: { fileSystem, notifications },\n    })\n\n    const mockStore: MockStoreCreator<ExplorerState.IExplorerState> = configureMockStore([\n        epicMiddleware,\n    ])\n\n    return mockStore\n}\n\ndescribe(\"ExplorerStore\", () => {\n    const rootPath = path.normalize(path.join(TestHelpers.getRootDirectory(), \"a\", \"test\", \"dir\"))\n    const filePath = path.join(rootPath, \"file.txt\")\n    const target = { filePath, id: \"1\" }\n\n    const pasted1 = {\n        type: \"file\",\n        filePath: \"/test/dir/afile.txt\",\n        id: \"1\",\n    }\n\n    const target1 = {\n        type: \"folder\",\n        folderPath: \"/test/dir/subdir/\",\n        id: \"1\",\n    }\n\n    const deleteAction = {\n        type: \"DELETE_SUCCESS\",\n        persist: true,\n        path: \"/test/dir\",\n        target: {\n            type: \"folder\",\n            folderPath: \"/test/dir/subdir\",\n            id: \"2\",\n            expanded: false,\n            name: \"subdir\",\n            indentationLevel: 2,\n        },\n    } as ExplorerState.IDeleteSuccessAction\n\n    const pasteAction = {\n        type: \"PASTE\",\n        target: target1,\n        pasted: [pasted1],\n        sources: [pasted1],\n    } as ExplorerState.IPasteAction\n\n    describe(\"SET_ROOT_DIRECTORY\", () => {\n        let store: Store<ExplorerState.IExplorerState>\n        let explorerFileSystem: MockedFileSystem\n\n        beforeEach(() => {\n            let fileSystem: any\n            fileSystem = new MemoryFileSystem()\n            fileSystem.mkdirpSync(rootPath)\n            fileSystem.writeFileSync(filePath, \"Hello World\")\n\n            explorerFileSystem = new MockedFileSystem(\n                new ExplorerFileSystem.FileSystem(fileSystem as any),\n            )\n            store = ExplorerState.createStore({\n                fileSystem: explorerFileSystem,\n                notifications: {} as any,\n            })\n        })\n\n        it(\"expands directory automatically\", async () => {\n            store.dispatch({\n                type: \"SET_ROOT_DIRECTORY\",\n                rootPath,\n            })\n\n            await TestHelpers.waitForAllAsyncOperations()\n            TestHelpers.tick(0) // execute setImmediate of memory-fs callbacks\n            await Promise.all(explorerFileSystem.promises)\n\n            const state = store.getState()\n\n            assert.deepEqual(\n                state.expandedFolders[rootPath],\n                [{ type: \"file\", fullPath: filePath }],\n                \"Validate expanded folders is set\",\n            )\n        })\n    })\n\n    describe(\"selectFileReducer\", () => {\n        it(\"returns state unchanged if action is not recognized\", () => {\n            const state = ExplorerState.selectFileReducer(\"shouldn't change\", {\n                type: \"UNRECOGNISED\",\n                filePath: \"not me\",\n            })\n            assert.equal(state, \"shouldn't change\")\n        })\n\n        it(\"flags pending file to select in state when given pending action\", () => {\n            const state = ExplorerState.selectFileReducer(\"should change\", {\n                type: \"SELECT_FILE_PENDING\",\n                filePath: \"change to me\",\n            })\n            assert.equal(state, \"change to me\")\n        })\n\n        it(\"resets pending file to select in state when given success action\", () => {\n            const state = ExplorerState.selectFileReducer(\"should change\", {\n                type: \"SELECT_FILE_SUCCESS\",\n            })\n            assert.equal(state, null)\n        })\n    })\n\n    describe(\"selectFileEpic\", () => {\n        let epicStore: any\n\n        beforeEach(() => {\n            epicStore = mockStoreFactory([ExplorerState.selectFileEpic])({\n                ...ExplorerState.DefaultExplorerState,\n                rootFolder: { type: \"folder\", fullPath: rootPath },\n            })\n        })\n\n        it(\"dispatches actions to expand folders and select file\", async () => {\n            const fileToSelect = path.normalize(path.join(rootPath, \"dir1\", \"dir2\", \"file.cpp\"))\n            epicStore.dispatch({ type: \"SELECT_FILE\", filePath: fileToSelect })\n            await TestHelpers.waitForAllAsyncOperations()\n            const actions = epicStore.getActions()\n            assert.deepStrictEqual(actions, [\n                { type: \"SELECT_FILE\", filePath: fileToSelect },\n                {\n                    type: \"EXPAND_DIRECTORY\",\n                    directoryPath: path.normalize(path.join(rootPath, \"dir1\")),\n                },\n                {\n                    type: \"EXPAND_DIRECTORY\",\n                    directoryPath: path.normalize(path.join(rootPath, \"dir1\", \"dir2\")),\n                },\n                { type: \"SELECT_FILE_PENDING\", filePath: fileToSelect },\n            ])\n        })\n\n        it(\"dispatches failure if target is not in workspace\", async () => {\n            const fileToSelect = path.normalize(path.join(TestHelpers.getRootDirectory(), \"other\"))\n            epicStore.dispatch({ type: \"SELECT_FILE\", filePath: fileToSelect })\n            await TestHelpers.waitForAllAsyncOperations()\n            const actions = epicStore.getActions()\n            assert.deepStrictEqual(actions, [\n                { type: \"SELECT_FILE\", filePath: fileToSelect },\n                { type: \"SELECT_FILE_FAIL\", reason: \"File is not in workspace: \" + fileToSelect },\n            ])\n        })\n    })\n\n    describe(\"notificationEpic\", () => {\n        let epicStore: any\n        let notifications: any\n        let notification: any\n\n        beforeEach(() => {\n            notifications = sinon.createStubInstance(Notifications)\n            notification = sinon.createStubInstance(Notification)\n            notifications.createItem.returns(notification)\n            epicStore = mockStoreFactory([ExplorerState.notificationEpic], notifications as any)({\n                ...ExplorerState.DefaultExplorerState,\n                rootFolder: { type: \"folder\", fullPath: rootPath },\n            })\n        })\n\n        it(\"notifies on failing to select a file in explorer\", () => {\n            epicStore.dispatch({ type: \"SELECT_FILE_FAIL\", reason: \"broken\" })\n            const actions = epicStore.getActions()\n\n            assert(notification.setContents.calledWith(\"Select Failed\", \"broken\"))\n            assert(notification.setLevel.calledWith(\"warn\"))\n            assert(notification.setExpiration.calledWith(5_000))\n            assert(notification.show.calledWith())\n            assert(notification.show.calledAfter(notification.setContents))\n            assert(notification.show.calledAfter(notification.setLevel))\n            assert(notification.show.calledAfter(notification.setExpiration))\n            assert.deepStrictEqual(actions, [\n                { type: \"SELECT_FILE_FAIL\", reason: \"broken\" },\n                { type: \"NOTIFICATION_SENT\", typeOfNotification: \"SELECT_FILE_FAIL\" },\n            ])\n        })\n    })\n\n    describe(\"YANK_AND_PASTE_EPICS\", async () => {\n        let fs: any\n\n        beforeEach(() => {\n            fs = new MockedFileSystem(new ExplorerFileSystem.FileSystem(new MemoryFileSystem()))\n        })\n        const notifications = {\n            _id: 0,\n            _overlay: null,\n            _overlayManager: null,\n            _store: null,\n            enable: true,\n            disable: false,\n            createItem: () => ({\n                setContents: (title: string, details: string) => ({ title, details }),\n                setLevel: (level: string) => ({ level }),\n                setExpiration: (expirationTime: number) => ({ expirationTime: 8_000 }),\n                show: () => ({}),\n            }),\n        } as any\n\n        const mockStore = mockStoreFactory([\n            ExplorerState.pasteEpic,\n            ExplorerState.clearYankRegisterEpic,\n        ])\n\n        it(\"dispatches a clear register action after a minute\", async () => {\n            const epicStore = mockStore({ ...ExplorerState.DefaultExplorerState })\n            epicStore.dispatch({ type: \"YANK\", target })\n            const actions = epicStore.getActions()\n            await TestHelpers.waitForAllAsyncOperations()\n            await assert.equal(actions.length, 2)\n            const clearedRegister = !!actions.find(action => action.type === \"CLEAR_REGISTER\")\n            assert.ok(clearedRegister)\n        })\n\n        it(\"should dispatch a paste success upon pasting successfully\", done => {\n            const action$ = ActionsObservable.of({\n                type: \"PASTE\",\n                target: target1,\n                pasted: [pasted1],\n                sources: [pasted1],\n            } as ExplorerState.ExplorerAction)\n\n            const expected = [\n                { type: \"CLEAR_REGISTER\", ids: [\"1\"] },\n                { type: \"EXPAND_DIRECTORY\", directoryPath: target1.folderPath },\n                { type: \"REFRESH\" },\n                {\n                    type: \"PASTE_SUCCESS\",\n                    moved: [\n                        { destination: path.join(target1.folderPath, \"afile.txt\"), node: pasted1 },\n                    ],\n                },\n            ]\n\n            ExplorerState.pasteEpic(action$, null, {\n                fileSystem: fs,\n                notifications,\n            })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.ok(actualActions.find(action => action.type === \"PASTE_SUCCESS\"))\n                    assert.deepEqual(actualActions, expected)\n                    done()\n                })\n        })\n\n        it(\"should correctly trigger a node deletion\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"DELETE\",\n                target: target1,\n                persist: true,\n            } as ExplorerState.IDeleteAction)\n\n            const expected = [\n                { type: \"DELETE_SUCCESS\", target: target1, persist: true },\n                { type: \"REFRESH\" },\n            ]\n\n            ExplorerState.deleteEpic(action$, null, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"should correctly dispatch a fail action if there is an error\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"DELETE\",\n                target: target1,\n                persist: true,\n            } as ExplorerState.IDeleteAction)\n\n            sinon.stub(fs, \"persistNode\").throws(new Error(\"Doesnt work\"))\n\n            const expected = [{ type: \"DELETE_FAIL\", reason: \"Doesnt work\" }]\n\n            ExplorerState.deleteEpic(action$, null, {\n                fileSystem: fs,\n                notifications,\n            })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should correctly trigger a move action on undo of paste\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"UNDO\",\n            } as ExplorerState.ExplorerAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    undo: [pasteAction],\n                },\n            }\n\n            const undoState = mockStore(state)\n            const expected = [{ type: \"UNDO_SUCCESS\" }, { type: \"REFRESH\" }]\n\n            ExplorerState.undoEpic(action$, undoState, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should trigger an expand directory on undo if the original source is a directory\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"UNDO\",\n            } as ExplorerState.ExplorerAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    undo: [{ ...pasteAction, sources: [target1] as ExplorerNode[] }],\n                },\n            }\n\n            const undoState = mockStore(state)\n            const expected = [\n                { type: \"UNDO_SUCCESS\" },\n                { type: \"EXPAND_DIRECTORY\", directoryPath: \"/test/dir/subdir/\" },\n                { type: \"REFRESH\" },\n            ]\n\n            ExplorerState.undoEpic(action$, undoState, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should trigger a restore action if the deleted note can be restored\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"UNDO\",\n            } as ExplorerState.ExplorerAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    undo: [deleteAction],\n                },\n            }\n\n            const undoState = mockStore(state)\n            const expected = [\n                { type: \"UNDO_SUCCESS\" },\n                { type: \"EXPAND_DIRECTORY\", directoryPath: \"/test/dir/subdir\" },\n                { type: \"REFRESH\" },\n            ]\n\n            ExplorerState.undoEpic(action$, undoState, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should return a fail action if the node was truly deleted\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"UNDO\",\n            } as ExplorerState.ExplorerAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    undo: [{ ...deleteAction, persist: false }],\n                },\n            }\n\n            const undoState = mockStore(state)\n            const expected = [\n                {\n                    type: \"UNDO_FAIL\",\n                    reason: \"The last deletion cannot be undone, sorry\",\n                } as ExplorerState.IUndoFailAction,\n            ]\n\n            ExplorerState.undoEpic(action$, undoState, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should clear updates after a short interval\", () => {\n            const action$ = ActionsObservable.of(deleteAction)\n\n            const expected = [\n                {\n                    type: \"CLEAR_UPDATE\",\n                } as ExplorerState.IClearUpdateAction,\n            ]\n\n            ExplorerState.clearUpdateEpic(action$, null, {\n                fileSystem: fs,\n                notifications,\n            })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should move an item when a rename is triggered\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"RENAME_COMMIT\",\n                target: target1,\n                newName: \"testing\",\n            } as ExplorerState.IRenameCommitAction)\n\n            const expected = [\n                {\n                    type: \"RENAME_SUCCESS\",\n                    targetType: \"folder\",\n                    source: target1.folderPath,\n                    destination: path.join(path.dirname(target1.folderPath), \"testing\"),\n                },\n                { type: \"REFRESH\" },\n            ]\n\n            ExplorerState.renameEpic(action$, null, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => assert.deepEqual(actualActions, expected))\n        })\n\n        it(\"Should send a notification on paste success\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"PASTE_SUCCESS\",\n                moved: [{ node: target1, destination: \"/another/test/dir\" }],\n            } as ExplorerState.IPasteSuccessAction)\n\n            const expected = [{ type: \"NOTIFICATION_SENT\", typeOfNotification: \"PASTE_SUCCESS\" }]\n\n            ExplorerState.notificationEpic(action$, null, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualAction => assert.deepEqual(actualAction, expected))\n        })\n\n        it(\"Should send a notification on paste fail\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"PASTE_FAIL\",\n            } as ExplorerState.IPasteFailAction)\n\n            const expected = [{ type: \"NOTIFICATION_SENT\", typeOfNotification: \"PASTE_FAIL\" }]\n\n            ExplorerState.notificationEpic(action$, null, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualAction => assert.deepEqual(actualAction, expected))\n        })\n\n        it(\"Should send a notification on rename success\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"RENAME_SUCCESS\",\n                source: \"/initial/test/dir\",\n                destination: \"/destination/test/dir\",\n                targetType: \"folder\",\n            } as ExplorerState.IRenameSuccessAction)\n\n            const expected = [{ type: \"NOTIFICATION_SENT\", typeOfNotification: \"RENAME_SUCCESS\" }]\n\n            ExplorerState.notificationEpic(action$, null, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualAction => assert.deepEqual(actualAction, expected))\n        })\n\n        it(\"Should send a notification on rename success\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"RENAME_FAIL\",\n            } as ExplorerState.IRenameFailAction)\n\n            const expected = [{ type: \"NOTIFICATION_SENT\", typeOfNotification: \"RENAME_FAIL\" }]\n\n            ExplorerState.notificationEpic(action$, null, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualAction => assert.deepEqual(actualAction, expected))\n        })\n\n        it(\"Should return a create node success action if a creation is committed\", async () => {\n            const action$ = ActionsObservable.of({\n                type: \"CREATE_NODE_COMMIT\",\n                name: \"/test/dir/file.txt\",\n            } as ExplorerState.ICreateNodeCommitAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    create: {\n                        active: true,\n                        nodeType: \"file\" as \"file\" | \"folder\",\n                        name: \"/test/dir/file.txt\",\n                    },\n                },\n            }\n\n            const createState = mockStore(state)\n\n            const expected = [\n                { type: \"CREATE_NODE_SUCCESS\", nodeType: \"file\", name: \"/test/dir/file.txt\" },\n                { type: \"SELECT_FILE\", filePath: \"/test/dir/file.txt\" },\n            ]\n\n            return ExplorerState.createNodeEpic(action$, createState, {\n                fileSystem: fs,\n                notifications,\n            })\n                .toArray()\n                .toPromise()\n                .then(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should return an error action if a creation fails\", async () => {\n            const action$ = ActionsObservable.of({\n                type: \"CREATE_NODE_COMMIT\",\n                name: \"/test/dir/file.txt\",\n            } as ExplorerState.ICreateNodeCommitAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    create: {\n                        active: true,\n                        nodeType: \"file\" as \"file\" | \"folder\",\n                        name: \"/test/dir/file.txt\",\n                    },\n                },\n            }\n\n            const createState = mockStore(state)\n\n            const expected = [{ type: \"CREATE_NODE_FAIL\", reason: \"Duplicate\" }]\n\n            return ExplorerState.createNodeEpic(action$, createState, {\n                fileSystem: {\n                    ...fs,\n                    writeFile: async folderpath => {\n                        throw new Error(\"Duplicate\")\n                    },\n                },\n                notifications,\n            })\n                .toArray()\n                .toPromise()\n                .then(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n\n        it(\"Should trigger a persist/delete action if the created node is undone\", () => {\n            const action$ = ActionsObservable.of({\n                type: \"UNDO\",\n            } as ExplorerState.ExplorerAction)\n\n            const stateCopy = clone(ExplorerState.DefaultExplorerState)\n            const state = {\n                ...stateCopy,\n                register: {\n                    ...stateCopy.register,\n                    undo: [\n                        {\n                            type: \"CREATE_NODE_SUCCESS\",\n                            name: \"/test/dir/file.txt\",\n                            nodeType: \"file\",\n                        } as ExplorerState.ICreateNodeSuccessAction,\n                    ],\n                },\n            }\n\n            const undoState = mockStore(state)\n            const expected = [{ type: \"UNDO_SUCCESS\" }, { type: \"REFRESH\" }]\n\n            ExplorerState.undoEpic(action$, undoState, { fileSystem: fs, notifications })\n                .toArray()\n                .subscribe(actualActions => {\n                    assert.deepEqual(actualActions, expected)\n                })\n        })\n    })\n\n    describe(\"Store utility helper tests\", () => {\n        it(\"Should not add an action if it isn't set to persist\", () => {\n            const testAction = {\n                type: \"DELETE_SUCCESS\",\n                persist: false,\n                target: { id: \"2\", type: \"file\", filePath },\n            } as ExplorerState.IDeleteSuccessAction\n            const newState = ExplorerState.shouldAddDeletion(testAction)\n            assert.ok(newState.length === 0 && Array.isArray(newState))\n        })\n\n        it(\"Should return an action if it is set to persist\", () => {\n            const testAction = {\n                type: \"DELETE_SUCCESS\",\n                persist: true,\n                target: { id: \"2\", type: \"file\", filePath },\n            } as ExplorerState.IDeleteSuccessAction\n            const newState = ExplorerState.shouldAddDeletion(testAction)\n            assert.deepEqual(head(newState), testAction)\n        })\n        describe(\"Register Reducer test\", () => {\n            const {\n                yankRegisterReducer,\n                DefaultExplorerState: { register },\n            } = ExplorerState\n\n            it(\"It should add paste items to both the paste and undo registers\", () => {\n                const newState = yankRegisterReducer(clone(register), pasteAction)\n                assert.deepEqual(\n                    newState.paste,\n                    pasteAction.target,\n                    \"Paste is set to the node which was the target of the paste action\",\n                )\n                assert.deepEqual(\n                    head(newState.undo),\n                    pasteAction,\n                    \"The paste action is saved in the undo queue\",\n                )\n            })\n\n            it(\"Should remove item from the end of the undo list following undo success\", () => {\n                const state = { ...register, undo: [pasteAction] }\n                const action = { type: \"UNDO_SUCCESS\" }\n                const newState = yankRegisterReducer(state, action)\n                assert.ok(!newState.undo.length)\n            })\n\n            it(\"Adds a delete action to the undo register IF it can be persisted)\", () => {\n                const newState = yankRegisterReducer(clone(register), deleteAction)\n                assert.deepEqual(head(newState.undo), deleteAction)\n            })\n\n            it(\"Does NOT Add a delete action to the undo register IF it can't be persisted)\", () => {\n                const newState = yankRegisterReducer(clone(register), {\n                    ...deleteAction,\n                    persist: false,\n                })\n                assert.ok(!newState.undo.length)\n            })\n\n            it(\"Should add a successful rename to undo register\", () => {\n                const newState = yankRegisterReducer(clone(register), {\n                    type: \"RENAME_SUCCESS\",\n                    destination: path.basename(target1.folderPath) + \"/rename\",\n                    source: target1.folderPath,\n                    targetType: \"folder\",\n                })\n\n                assert.ok(newState.undo.length === 1)\n            })\n\n            it(\"Should clear the renaming if a rename cancel action is triggered\", () => {\n                const state = {\n                    ...clone(register),\n                    rename: {\n                        target: target1 as ExplorerNode,\n                        active: true,\n                    },\n                }\n                const newState = yankRegisterReducer(state, { type: \"RENAME_CANCEL\" })\n                assert.ok(!newState.rename.active)\n                assert.ok(!newState.rename.target)\n            })\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/FileMappingsTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as path from \"path\"\n\nconst MemoryFileSystem = require(\"memory-fs\") // tslint:disable-line\n\nimport * as FileMappings from \"./../../src/Services/FileMappings\"\n\ndescribe(\"FileMappings\", () => {\n    let rootPath: string\n    let srcPath: string\n    let testPath: string\n    let fileSystem: any\n\n    beforeEach(() => {\n        rootPath = path.join(\"C:/\", \"oni-unit-test-container\")\n        srcPath = path.join(rootPath, \"browser\", \"src\")\n        testPath = path.join(rootPath, \"browser\", \"test\")\n\n        fileSystem = new MemoryFileSystem()\n        fileSystem.mkdirpSync(srcPath)\n        fileSystem.mkdirpSync(testPath)\n    })\n\n    describe(\"getMappedFile\", () => {\n        it(\"returns null for template file if template file doesn't exist\", () => {\n            const srcFile = path.join(srcPath, \"source.ts\")\n\n            const mapping: FileMappings.IFileMapping = {\n                sourceFolder: \"browser/src\",\n\n                mappedFolder: \"browser/test\",\n                mappedFileName: \"${fileName}Test.ts\", // tslint:disable-line\n            }\n\n            const mappedFile = FileMappings.getMappedFile(rootPath, srcFile, [mapping])\n\n            assert.strictEqual(\n                mappedFile.templateFileFullPath,\n                null,\n                \"`templateFileFullPath` should be null since there is no template file specified.\",\n            )\n        })\n\n        it(\"returns a template file if template file exists\", () => {\n            const srcFile = path.join(srcPath, \"source.ts\")\n\n            const mapping: FileMappings.IFileMapping = {\n                sourceFolder: \"browser/src\",\n\n                mappedFolder: \"browser/test\",\n                mappedFileName: \"${fileName}Test.ts\", // tslint:disable-line\n\n                templateFilePath: \"templates/template.ts\",\n            }\n\n            const mappedFile = FileMappings.getMappedFile(rootPath, srcFile, [mapping])\n\n            assert.strictEqual(\n                mappedFile.templateFileFullPath,\n                path.join(rootPath, mapping.templateFilePath),\n            )\n        })\n    })\n\n    describe(\"getMappedFileFromMapping\", () => {\n        it(\"returns simple mapping\", () => {\n            const srcFile = path.join(srcPath, \"source.ts\")\n            const testFile = path.join(testPath, \"sourceTest.ts\")\n\n            fileSystem.writeFileSync(srcFile, \" \")\n            fileSystem.writeFileSync(testFile, \" \")\n\n            const mapping: FileMappings.IFileMapping = {\n                sourceFolder: \"browser/src\",\n\n                mappedFolder: \"browser/test\",\n                mappedFileName: \"${fileName}Test.ts\", // tslint:disable-line\n            }\n\n            const mappedFile = FileMappings.getMappedFileFromMapping(rootPath, srcFile, mapping)\n            assert.strictEqual(mappedFile, testFile, \"Validate mapping worked correctly\")\n        })\n\n        it(\"works with recursive directories\", () => {\n            const nestedSrcFolder = path.join(srcPath, \"nested\", \"a\")\n            const nestedTestFolder = path.join(testPath, \"nested\", \"a\")\n\n            fileSystem.mkdirpSync(nestedSrcFolder)\n            fileSystem.mkdirpSync(nestedTestFolder)\n\n            const srcFile = path.join(nestedSrcFolder, \"source.ts\")\n            const testFile = path.join(nestedTestFolder, \"source.test.ts\")\n\n            fileSystem.writeFileSync(srcFile, \" \")\n            fileSystem.writeFileSync(testFile, \" \")\n\n            const mapping: FileMappings.IFileMapping = {\n                sourceFolder: \"browser/src\",\n\n                mappedFolder: \"browser/test\",\n                mappedFileName: \"${fileName}.test.ts\", // tslint:disable-line\n            }\n\n            const mappedFile = FileMappings.getMappedFileFromMapping(rootPath, srcFile, mapping)\n            assert.strictEqual(mappedFile, testFile, \"Validate mapping worked correctly\")\n        })\n    })\n\n    describe(\"getPathDifference\", () => {\n        it(\"resolves path correctly\", () => {\n            const diff = FileMappings.getPathDifference(\"D:/test1/test2\", \"D:/test1/test2/test3\")\n            assert.strictEqual(diff, \"test3\")\n        })\n\n        it(\"resolves path correctly, in reverse\", () => {\n            const diff = FileMappings.getPathDifference(\"D:/test1/test2/test3\", \"D:/test1/test2\")\n            assert.strictEqual(diff, \"test3\")\n        })\n\n        it(\"handles case where there is no common path\", () => {\n            const diff = FileMappings.getPathDifference(\"D:/test1\", \"C:/test2\")\n            assert.strictEqual(diff, path.join(\"D:\", \"test1\"))\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Language/EditTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { sortTextEdits } from \"./../../../src/Services/Language/Edits\"\n\ndescribe(\"sortTextEdits\", () => {\n    it(\"sorts descending by lines\", () => {\n        const rangeLine1 = types.Range.create(1, 0, 1, 0)\n        const rangeLine2 = types.Range.create(2, 0, 2, 0)\n\n        const edit1 = types.TextEdit.del(rangeLine1)\n        const edit2 = types.TextEdit.del(rangeLine2)\n\n        const ranges = [edit1, edit2]\n\n        const sortedRanges = sortTextEdits(ranges)\n\n        assert.deepEqual(sortedRanges, [edit2, edit1])\n    })\n\n    it(\"sorts descending inside lines\", () => {\n        const rangeLine1 = types.Range.create(1, 1, 1, 5)\n        const rangeLine2 = types.Range.create(1, 10, 1, 15)\n\n        const edit1 = types.TextEdit.del(rangeLine1)\n        const edit2 = types.TextEdit.del(rangeLine2)\n\n        const ranges = [edit1, edit2]\n        const sortedRanges = sortTextEdits(ranges)\n\n        assert.deepEqual(sortedRanges, [edit2, edit1])\n    })\n\n    it(\"sorts first by lines, then by characters\", () => {\n        const rangeLine1 = types.Range.create(1, 1, 1, 5)\n        const rangeLine2 = types.Range.create(1, 10, 1, 15)\n        const rangeLine3 = types.Range.create(2, 1, 2, 5)\n        const rangeLine4 = types.Range.create(2, 10, 2, 15)\n\n        const edit1 = types.TextEdit.del(rangeLine1)\n        const edit2 = types.TextEdit.del(rangeLine2)\n        const edit3 = types.TextEdit.del(rangeLine3)\n        const edit4 = types.TextEdit.del(rangeLine4)\n\n        const edits = [edit1, edit2, edit3, edit4]\n        const sortedEdits = sortTextEdits(edits)\n\n        assert.deepEqual(sortedEdits, [edit4, edit3, edit2, edit1])\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Language/LanguageEditorIntegrationTests.ts",
    "content": "/**\n * LanguageEditorIntegrationTests\n */\n\nimport * as assert from \"assert\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Language from \"./../../../src/Services/Language\"\n\nimport * as Mocks from \"./../../Mocks\"\n\nconst createSuccessfulDefinitionResult = (): Language.IDefinitionResult => {\n    return {\n        location: types.Location.create(\"testuri\", types.Range.create(1, 1, 5, 5)),\n        token: {\n            tokenName: \"test\",\n            range: types.Range.create(1, 1, 2, 2),\n        },\n    }\n}\n\ndescribe(\"LanguageEditorIntegration\", () => {\n    const clock: any = global[\"clock\"] // tslint:disable-line\n    const waitForPromiseResolution: any = global[\"waitForPromiseResolution\"] // tslint:disable-line\n\n    // Mocks\n    let mockConfiguration: Mocks.MockConfiguration\n    let mockEditor: Mocks.MockEditor\n    let mockDefinitionRequestor: Mocks.MockDefinitionRequestor\n    let mockHoverRequestor: Mocks.MockHoverRequestor\n\n    // Class under test\n    let languageEditorIntegration: Language.LanguageEditorIntegration\n\n    beforeEach(() => {\n        mockConfiguration = new Mocks.MockConfiguration({\n            \"editor.definition.enabled\": true,\n            \"editor.quickInfo.delay\": 500,\n            \"editor.quickInfo.enabled\": true,\n        })\n\n        mockEditor = new Mocks.MockEditor()\n        mockDefinitionRequestor = new Mocks.MockDefinitionRequestor()\n        mockHoverRequestor = new Mocks.MockHoverRequestor()\n        languageEditorIntegration = new Language.LanguageEditorIntegration(\n            mockEditor,\n            mockConfiguration as any,\n            null,\n            mockDefinitionRequestor,\n            mockHoverRequestor,\n        )\n    })\n\n    afterEach(() => {\n        languageEditorIntegration.dispose()\n    })\n\n    it(\"shows hover and definition\", async () => {\n        let showDefinitionCount = 0\n        let showHoverCount = 0\n\n        languageEditorIntegration.onShowDefinition.subscribe(() => showDefinitionCount++)\n        languageEditorIntegration.onShowHover.subscribe(() => showHoverCount++)\n\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        clock.tick(501) // Account for the quickInfo.delay\n\n        assert.strictEqual(mockDefinitionRequestor.pendingCallCount, 1)\n        assert.strictEqual(mockHoverRequestor.pendingCallCount, 1)\n\n        // Resolve the calls\n        mockDefinitionRequestor.resolve(createSuccessfulDefinitionResult())\n        mockHoverRequestor.resolve({} as any)\n\n        await waitForPromiseResolution()\n\n        clock.runAll()\n\n        assert.strictEqual(showDefinitionCount, 1, \"Definition was shown\")\n        assert.strictEqual(showHoverCount, 1, \"Hover was shown\")\n    })\n\n    it(\"respects editor.quickInfo.delay setting for hover\", () => {\n        // Get the editor primed for a request\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        // There shouldn't be any requests yet, because\n        // we haven't hit the delay..\n        assert.strictEqual(\n            mockHoverRequestor.pendingCallCount,\n            0,\n            \"Should be no request queued yet...\",\n        )\n\n        // Tick just before the delay....\n        clock.tick(499)\n\n        assert.strictEqual(\n            mockHoverRequestor.pendingCallCount,\n            0,\n            \"Should be no request queued, right before the time limit..\",\n        )\n\n        // Tick just after the delay...\n        clock.tick(2)\n\n        // There should now be a request queued up\n        assert.strictEqual(\n            mockHoverRequestor.pendingCallCount,\n            1,\n            \"Should now be a request pending, because we've exceeded the limit\",\n        )\n    })\n\n    it(\"doesn't show slow hover response that completes after cursor moves\", async () => {\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        let hoverShowCount = 0\n\n        languageEditorIntegration.onShowHover.subscribe(() => hoverShowCount++)\n\n        // Go past the clock timer, so we should get a request now\n        clock.tick(501)\n\n        assert.strictEqual(\n            mockHoverRequestor.pendingCallCount,\n            1,\n            \"Verify we have a request queued up\",\n        )\n\n        // While the request is pending, lets move the cursor\n\n        mockEditor.simulateCursorMoved(2, 2)\n\n        // Complete the hover request, and let the promises drain\n        mockHoverRequestor.resolve({} as any)\n        await waitForPromiseResolution()\n\n        // Let clock drain as well\n        clock.runAll()\n\n        assert.strictEqual(\n            hoverShowCount,\n            0,\n            \"Hover should never be shown, because the cursor moved.\",\n        )\n    })\n\n    it(\"doesn't show slow hover response that completes after mode changes\", async () => {\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        let hoverShowCount = 0\n\n        languageEditorIntegration.onShowHover.subscribe(() => hoverShowCount++)\n\n        // Go past the clock timer, so we should get a request now\n        clock.tick(501)\n\n        assert.strictEqual(\n            mockHoverRequestor.pendingCallCount,\n            1,\n            \"Verify we have a request queued up\",\n        )\n\n        // While the request is pending, lets move the cursor\n\n        mockEditor.simulateModeChange(\"insert\")\n\n        // Complete the hover request, and let the promises drain\n        mockHoverRequestor.resolve({} as any)\n        await waitForPromiseResolution()\n\n        // Let clock drain as well\n        clock.runAll()\n\n        assert.strictEqual(\n            hoverShowCount,\n            0,\n            \"Hover should never be shown, because the cursor moved.\",\n        )\n    })\n\n    it(\"hides hover on mode change\", async () => {\n        let showHoverCount = 0\n        let hideHoverCount = 0\n\n        languageEditorIntegration.onShowHover.subscribe(() => showHoverCount++)\n        languageEditorIntegration.onHideHover.subscribe(() => hideHoverCount++)\n\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        clock.tick(501) // Account for the quickInfo.delay\n\n        assert.strictEqual(mockHoverRequestor.pendingCallCount, 1)\n\n        // Resolve the calls\n        mockHoverRequestor.resolve({} as any)\n\n        await waitForPromiseResolution()\n\n        clock.runAll()\n\n        assert.strictEqual(showHoverCount, 1, \"Hover was shown\")\n        assert.strictEqual(hideHoverCount, 0, \"No calls to hide hover yet\")\n\n        mockEditor.simulateModeChange(\"cmdline\")\n\n        clock.runAll()\n\n        assert.strictEqual(showHoverCount, 1, \"Hover show count should be unchanged\")\n        assert.strictEqual(hideHoverCount, 1, \"There should now be a call to hide the hover\")\n    })\n\n    it(\"#1063 - doesn't show hover if there are no results\", async () => {\n        let showDefinitionCount = 0\n\n        languageEditorIntegration.onShowDefinition.subscribe(() => showDefinitionCount++)\n\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        clock.tick(501) // Account for the quickInfo.delay\n\n        assert.strictEqual(mockDefinitionRequestor.pendingCallCount, 1)\n\n        // Resolve the calls, simulating a null result\n        // to reproduce the issue in #1063.\n        //\n        // In the case where we don't get a result,\n        // we could still have a value for `token`,\n        // but not `location`.\n        mockDefinitionRequestor.resolve({\n            token: {\n                tokenName: \"test\",\n                range: null,\n            },\n            location: null,\n        })\n\n        await waitForPromiseResolution()\n\n        clock.runAll()\n\n        assert.strictEqual(showDefinitionCount, 0, \"Definition should not be shown\")\n    })\n\n    it(\"#1247 - shows definition, even if hover is not enabled\", async () => {\n        mockConfiguration.setValue(\"editor.quickInfo.enabled\", false)\n\n        let showDefinitionCount = 0\n        languageEditorIntegration.onShowDefinition.subscribe(() => showDefinitionCount++)\n\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        clock.tick(501) // Account for the quickInfo.delay\n\n        assert.strictEqual(mockDefinitionRequestor.pendingCallCount, 1)\n\n        // Resolve the calls\n        mockDefinitionRequestor.resolve(createSuccessfulDefinitionResult())\n\n        await waitForPromiseResolution()\n\n        clock.runAll()\n\n        assert.strictEqual(\n            showDefinitionCount,\n            1,\n            \"Definition should be shown, even if 'editor.quickInfo.enabled' is false.\",\n        )\n    })\n\n    it(\"#1247 - doesn't show definition if 'editor.definition.enabled' is false\", async () => {\n        mockConfiguration.setValue(\"editor.definition.enabled\", false)\n\n        mockEditor.simulateModeChange(\"normal\")\n        mockEditor.simulateBufferEnter(new Mocks.MockBuffer())\n        mockEditor.simulateCursorMoved(1, 1)\n\n        clock.tick(501) // Account for the quickInfo.delay\n\n        assert.strictEqual(\n            mockDefinitionRequestor.pendingCallCount,\n            0,\n            \"Validate no request pending for definitions\",\n        )\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Language/LanguageManagerTests.ts",
    "content": "/**\n * LanguageEditorIntegrationTests\n */\n\nimport * as assert from \"assert\"\n\nimport * as sinon from \"sinon\"\n\nimport { Event } from \"oni-types\"\n\nimport * as Language from \"./../../../src/Services/Language\"\n\nimport * as Mocks from \"./../../Mocks\"\nimport * as TestHelpers from \"./../../TestHelpers\"\n\nexport class MockLanguageClient implements Language.ILanguageClient {\n    public serverCapabilities: any = {}\n\n    public subscribe(notificationName: string, evt: Event<any>): void {\n        // tslint: disable-line\n    }\n\n    public handleRequest(requestName: string, handler: Language.RequestHandler): void {\n        // tslint: disable-line\n    }\n\n    public sendRequest<T>(\n        fileName: string,\n        requestName: string,\n        protocolArguments: Language.NotificationValueOrThunk,\n    ): Promise<T> {\n        return Promise.resolve(null)\n    }\n\n    public sendNotification(\n        fileName: string,\n        notificationName: string,\n        protocolArguments: Language.NotificationValueOrThunk,\n    ): void {\n        // tslint: disable-line\n    }\n}\n\ndescribe(\"LanguageManager\", () => {\n    // Mocks\n    let mockOni: Mocks.MockOni\n\n    // Class under test\n    let languageManager: Language.LanguageManager\n\n    beforeEach(() => {\n        const mockConfiguration = new Mocks.MockConfiguration({\n            \"editor.quickInfo.delay\": 500,\n            \"editor.quickInfo.enabled\": true,\n            \"status.priority\": {\n                \"oni.status.workingDirectory\": 0,\n                \"oni.status.linenumber\": 1,\n                \"oni.status.mode\": 0,\n                \"oni.status.filetype\": 1,\n                \"oni.status.git\": 2,\n            },\n        })\n        mockOni = new Mocks.MockOni(mockConfiguration)\n\n        languageManager = new Language.LanguageManager(mockOni)\n    })\n\n    it(\"sends didOpen request if language server is registered after enter event\", async () => {\n        // Simulate entering a buffer _before_ the language server is registered\n        // This can happen if a plugin registers a language server, because we spin\n        // up the editors before initializing plugins.\n        const mockBuffer = new Mocks.MockBuffer(\"javascript\", \"test.js\", [\"a\", \"b\", \"c\"])\n        const mockEditor = mockOni.editors.activeEditor as Mocks.MockEditor\n        mockEditor.simulateBufferEnter(mockBuffer)\n\n        const mockLanguageClient = new MockLanguageClient()\n\n        const sendRequestSpy = sinon.spy(mockLanguageClient, \"sendNotification\")\n\n        // Validate that after registering the client, we had a call to 'textDocument/didOpen'\n        // with the contents of the buffer.\n        languageManager.registerLanguageClient(\"javascript\", mockLanguageClient)\n\n        // Wait for any pending promises to drain\n        await TestHelpers.waitForPromiseResolution()\n\n        // Verify \"sendNotification\" was called\n        assert.strictEqual(sendRequestSpy.callCount, 1)\n\n        const [filePath, notificationName] = sendRequestSpy.getCall(0).args\n\n        assert.strictEqual(filePath, \"test.js\")\n        assert.strictEqual(notificationName, \"textDocument/didOpen\")\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Learning/Achievements/AchievementsManagerTests.ts",
    "content": "/**\n * AchievementsManagerTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport {\n    AchievementDefinition,\n    AchievementsManager,\n    IPersistedAchievementState,\n} from \"./../../../../src/Services/Learning/Achievements\"\n\nimport { MockPersistentStore } from \"./../../../Mocks\"\n\nconst createTestAchievement = (uniqueId: string, goalId: string) => ({\n    uniqueId,\n    name: \"some test achievement\",\n    description: \"some test achievement description\",\n    goals: [\n        {\n            name: \"some test name\",\n            goalId,\n            count: 1,\n        },\n    ],\n})\n\ndescribe(\"AchievementsManagerTests\", () => {\n    let mockStore: MockPersistentStore<IPersistedAchievementState>\n\n    beforeEach(() => {\n        mockStore = new MockPersistentStore<IPersistedAchievementState>({\n            goalCounts: {},\n            achievedIds: [],\n        })\n    })\n\n    it(\"fires onAchievementAccomplished when an achievement is accomplished\", async () => {\n        const achievementsManager = new AchievementsManager(mockStore)\n        await achievementsManager.start()\n\n        let hitCount = 0\n        achievementsManager.onAchievementAccomplished.subscribe(() => {\n            hitCount++\n        })\n\n        const achievement = createTestAchievement(\"test.achievement\", \"test.goal\")\n        achievementsManager.registerAchievement(achievement)\n\n        achievementsManager.notifyGoal(\"test.goal\")\n        assert.strictEqual(hitCount, 1, \"Validate that onAchievementsAccomplished was fired\")\n    })\n\n    it(\"doesn't fire onAchievementAccomplished if an achievement was already accomplished prior to tracking\", async () => {\n        await mockStore.set({\n            goalCounts: {},\n            achievedIds: [\"test.achievement\"],\n        })\n\n        const achievementsManager = new AchievementsManager(mockStore)\n        await achievementsManager.start()\n\n        let hitCount = 0\n        achievementsManager.onAchievementAccomplished.subscribe(() => {\n            hitCount++\n        })\n\n        const achievement = createTestAchievement(\"test.achievement\", \"test.goal\")\n\n        // Notify goal BEFORE the achievement is registered\n        achievementsManager.notifyGoal(\"test.goal\")\n\n        achievementsManager.registerAchievement(achievement)\n\n        assert.strictEqual(hitCount, 0, \"Validate that onAchievementsAccomplished was not fired\")\n    })\n\n    it(\"does fire onAchievementAccomplished if goals are met, but it hasn't been accomplished yet\", async () => {\n        const achievementsManager = new AchievementsManager(mockStore)\n        await achievementsManager.start()\n\n        let hitCount = 0\n        achievementsManager.onAchievementAccomplished.subscribe(() => {\n            hitCount++\n        })\n\n        achievementsManager.notifyGoal(\"test.goal\")\n\n        const achievement = createTestAchievement(\"test.achievement\", \"test.goal\")\n        achievementsManager.registerAchievement(achievement)\n\n        assert.strictEqual(hitCount, 1, \"Validate that onAchievementsAccomplished was fired\")\n    })\n\n    describe(\"dependent achievements\", () => {\n        let achievementsManager: AchievementsManager\n        let coreAchievement: AchievementDefinition\n        let dependentAchievement: AchievementDefinition\n\n        beforeEach(async () => {\n            achievementsManager = new AchievementsManager(mockStore)\n            await achievementsManager.start()\n\n            coreAchievement = createTestAchievement(\"test.achievement.core\", \"test.goal\")\n            dependentAchievement = createTestAchievement(\"test.achievement.dependent\", \"test.goal\")\n            dependentAchievement.dependsOnId = \"test.achievement.core\"\n\n            achievementsManager.registerAchievement(coreAchievement)\n            achievementsManager.registerAchievement(dependentAchievement)\n        })\n\n        it(\"is locked until dependent achievement is accomplished\", () => {\n            const progress = achievementsManager.getAchievements()\n\n            const coreResult = progress.find(\n                a => a.achievement.uniqueId === \"test.achievement.core\",\n            )\n            const dependentResult = progress.find(\n                a => a.achievement.uniqueId === \"test.achievement.dependent\",\n            )\n\n            assert.strictEqual(coreResult.locked, false)\n            assert.strictEqual(dependentResult.locked, true)\n\n            achievementsManager.notifyGoal(\"test.goal\")\n\n            const progressAfterFirstGoal = achievementsManager.getAchievements()\n            const coreResultAfter = progressAfterFirstGoal.find(\n                a => a.achievement.uniqueId === \"test.achievement.core\",\n            )\n            const dependentResultAfter = progressAfterFirstGoal.find(\n                a => a.achievement.uniqueId === \"test.achievement.dependent\",\n            )\n\n            assert.strictEqual(coreResultAfter.completed, true)\n            // The dependent result should no longer be locked\n            assert.strictEqual(dependentResultAfter.locked, false)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Learning/Tutorial/TutorialGameplayManagerTests.ts",
    "content": "/**\n * TutorialGameplayManagerTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { MockEditor } from \"./../../../Mocks\"\nimport * as TestHelpers from \"./../../../TestHelpers\"\n\nimport { ITutorialMetadata } from \"./../../../../src/Services/Learning/Tutorial\"\nimport {\n    TICK_RATE,\n    TutorialGameplayManager,\n} from \"./../../../../src/Services/Learning/Tutorial/TutorialGameplayManager\"\n\nconst MockTutorialMetadata: ITutorialMetadata = {\n    id: \"tutorial.test\",\n    name: \"test tutorial\",\n    description: \"tutorial for unit tests\",\n    level: -1,\n}\n\n// Helper to execute a 'tick', so that the 'setInterval' that runs the ticks\n// gets picked up\nconst tick = async () => {\n    await TestHelpers.waitForPromiseResolution()\n    TestHelpers.tick(TICK_RATE + 1)\n}\n\ndescribe(\"TutorialGameplayManagerTests\", () => {\n    let mockEditor: Oni.Editor = null\n    let tutorialGameplayManager: TutorialGameplayManager = null\n\n    beforeEach(() => {\n        mockEditor = new MockEditor()\n        tutorialGameplayManager = new TutorialGameplayManager(mockEditor)\n    })\n\n    it(\"calls tick periodically while active\", async () => {\n        let hitCount = 0\n\n        const tickFunction = () => {\n            hitCount++\n            return Promise.resolve(false)\n        }\n\n        const myTutorial = {\n            metadata: MockTutorialMetadata,\n            stages: [\n                {\n                    tickFunction,\n                },\n            ],\n        }\n\n        tutorialGameplayManager.start(myTutorial, mockEditor.activeBuffer)\n\n        // Validate the tick function was executed\n        assert.strictEqual(hitCount, 1)\n\n        // Validate that another 'tick' was executed\n        await tick()\n        assert.strictEqual(hitCount, 2)\n\n        tutorialGameplayManager.stop()\n\n        // Validate that there wasn't another tick after stopping\n        await tick()\n        assert.strictEqual(hitCount, 2)\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Learning/Tutorial/TutorialManagerTests.ts",
    "content": "/**\n * TutorialManagerTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { EditorManager } from \"./../../../../src/Services/EditorManager\"\nimport {\n    IPersistedTutorialState,\n    ITutorial,\n    TutorialManager,\n} from \"./../../../../src/Services/Learning/Tutorial\"\nimport { WindowManager } from \"./../../../../src/Services/WindowManager\"\n\nimport * as Mocks from \"./../../../Mocks\"\n\nconst createMockTutorial = (\n    tutorialId: string,\n    tutorialName: string,\n    level: number = 100,\n): ITutorial => {\n    return {\n        metadata: {\n            id: tutorialId,\n            name: tutorialName,\n            description: \"test description\",\n            level,\n        },\n        stages: [] as any[],\n    }\n}\n\ndescribe(\"TutorialManagerTests\", () => {\n    let mockEditor: Mocks.MockEditor\n    let mockStore: Mocks.MockPersistentStore<IPersistedTutorialState>\n    let editorManager: EditorManager\n    let windowManager: WindowManager\n    let tutorialManager: TutorialManager\n\n    beforeEach(() => {\n        mockEditor = new Mocks.MockEditor()\n        mockStore = new Mocks.MockPersistentStore<IPersistedTutorialState>({\n            completionInfo: {},\n        })\n        editorManager = new EditorManager()\n        windowManager = new WindowManager()\n        editorManager.setActiveEditor(mockEditor as any)\n\n        tutorialManager = new TutorialManager(editorManager, mockStore, windowManager)\n    })\n\n    describe(\"registerTutorial\", () => {\n        it(\"adds a tutorial\", async () => {\n            const tutorial = createMockTutorial(\"test.tutorial.1\", \"test tutorial\")\n            tutorialManager.registerTutorial(tutorial)\n\n            const tutorials = tutorialManager.getTutorialInfo()\n\n            assert.strictEqual(tutorials.length, 1)\n        })\n    })\n\n    describe(\"getTutorialInfo\", () => {\n        it(\"returns tutorials sorted by level\", async () => {\n            const tutorial1 = createMockTutorial(\"test.tutorial.1\", \"test tutorial1\", 1)\n            tutorialManager.registerTutorial(tutorial1)\n\n            const tutorial0 = createMockTutorial(\"test.tutorial.0\", \"test tutorial0\", 0)\n            tutorialManager.registerTutorial(tutorial0)\n\n            const tutorials = tutorialManager.getTutorialInfo()\n            assert.strictEqual(tutorials.length, 2)\n\n            // Validate the tutorials are sorted by their 'level'\n            assert.strictEqual(tutorials[0].tutorialInfo.id, \"test.tutorial.0\")\n            assert.strictEqual(tutorials[1].tutorialInfo.id, \"test.tutorial.1\")\n        })\n    })\n\n    describe(\"getNextTutorialId\", () => {\n        it(\"gets next incomplete tutorial if null\", async () => {\n            await tutorialManager.start()\n\n            const tutorial0 = createMockTutorial(\"test.tutorial.0\", \"test tutorial0\", 0)\n            tutorialManager.registerTutorial(tutorial0)\n\n            const tutorial1 = createMockTutorial(\"test.tutorial.1\", \"test tutorial1\", 1)\n            tutorialManager.registerTutorial(tutorial1)\n\n            const tutorial2 = createMockTutorial(\"test.tutorial.2\", \"test tutorial2\", 2)\n            tutorialManager.registerTutorial(tutorial2)\n\n            await tutorialManager.notifyTutorialCompleted(\"test.tutorial.0\", {\n                keyPresses: 10,\n                time: 1521,\n            })\n\n            await tutorialManager.notifyTutorialCompleted(\"test.tutorial.1\", {\n                keyPresses: 10,\n                time: 1521,\n            })\n\n            const nextTutorial = tutorialManager.getNextTutorialId()\n            assert.strictEqual(nextTutorial, \"test.tutorial.2\")\n        })\n\n        it(\"gets tutorial in sequence\", async () => {\n            await tutorialManager.start()\n\n            const tutorial0 = createMockTutorial(\"test.tutorial.0\", \"test tutorial0\", 0)\n            tutorialManager.registerTutorial(tutorial0)\n\n            const tutorial1 = createMockTutorial(\"test.tutorial.1\", \"test tutorial1\", 1)\n            tutorialManager.registerTutorial(tutorial1)\n\n            const tutorial2 = createMockTutorial(\"test.tutorial.2\", \"test tutorial2\", 2)\n            tutorialManager.registerTutorial(tutorial2)\n\n            const nextTutorial = tutorialManager.getNextTutorialId(\"test.tutorial.1\")\n            assert.strictEqual(nextTutorial, \"test.tutorial.2\")\n        })\n    })\n\n    describe(\"notifyTutorialCompleted\", () => {\n        it(\"dispatches 'onTutorialCompletedEvent' when a tutorial is completed\", async () => {\n            await tutorialManager.start()\n\n            const tutorial0 = createMockTutorial(\"test.tutorial.0\", \"test tutorial0\", 0)\n            tutorialManager.registerTutorial(tutorial0)\n\n            let hitCount = 0\n            tutorialManager.onTutorialCompletedEvent.subscribe(() => {\n                hitCount++\n            })\n\n            await tutorialManager.notifyTutorialCompleted(\"test.tutorial.0\", {\n                keyPresses: 10,\n                time: 1522,\n            })\n\n            assert.strictEqual(hitCount, 1, \"Validate event was dispatched\")\n        })\n\n        it(\"persists completion data to the store\", async () => {\n            await tutorialManager.start()\n\n            const tutorial0 = createMockTutorial(\"test.tutorial.0\", \"test tutorial0\", 0)\n            tutorialManager.registerTutorial(tutorial0)\n\n            await tutorialManager.notifyTutorialCompleted(\"test.tutorial.0\", {\n                keyPresses: 10,\n                time: 1522,\n            })\n\n            const completionInfo = await mockStore.get()\n\n            const expectedInfo = {\n                completionInfo: {\n                    \"test.tutorial.0\": {\n                        keyPresses: 10,\n                        time: 1522,\n                    },\n                },\n            }\n\n            assert.deepEqual(completionInfo, expectedInfo, \"Validate info was persisted\")\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Menu/MenuReducerTests.ts",
    "content": "import * as assert from \"assert\"\nimport * as sinon from \"sinon\"\n\nimport { createReducer } from \"../../../src/Services/Menu/MenuReducer\"\nimport { createDefaultState } from \"../../../src/Services/Menu/MenuState\"\n\ndescribe(\"MenuReducer\", () => {\n    let reducer: any\n    let oldState: any\n\n    beforeEach(() => {\n        reducer = createReducer<any, any>()\n        oldState = createDefaultState<any, any>()\n        oldState.menu = {}\n    })\n\n    describe(\"popupMenuReducer\", () => {\n        describe(\"FILTER_MENU\", () => {\n            let filteredOptions: any\n            let filterFunction: any\n\n            beforeEach(() => {\n                filteredOptions = {}\n                filterFunction = sinon.stub().returns(filteredOptions)\n                oldState.menu.filterFunction = filterFunction\n            })\n\n            it(\"resets selectedIndex to zero\", () => {\n                oldState.menu.selectedIndex = 123\n\n                const newState = reducer(oldState, {\n                    type: \"FILTER_MENU\",\n                    payload: { filter: \"mock filter\" },\n                })\n\n                assert.deepStrictEqual(newState, {\n                    ...oldState,\n                    menu: {\n                        filter: \"mock filter\",\n                        filterFunction,\n                        filteredOptions,\n                        selectedIndex: 0,\n                    },\n                })\n            })\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Notifications/NotificationStoreTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport { createStore } from \"./../../../src/Services/Notifications/NotificationStore\"\n\ndescribe(\"NotificationStore\", () => {\n    it(\"'SHOW_NOTIFICATION' adds a notification store\", () => {\n        const store = createStore()\n\n        // tslint:disable-next-line\n        const testFunc = () => {}\n\n        store.dispatch({\n            type: \"SHOW_NOTIFICATION\",\n            id: \"test_notification\",\n            title: \"title-test\",\n            detail: \"detail-test\",\n            buttons: null,\n            expirationTime: null,\n            level: \"info\",\n            onClick: testFunc,\n            onClose: testFunc,\n        })\n\n        const state = store.getState()\n\n        assert.deepEqual(state.notifications, {\n            [\"test_notification\"]: {\n                id: \"test_notification\",\n                title: \"title-test\",\n                detail: \"detail-test\",\n                buttons: null,\n                expirationTime: null,\n                level: \"info\",\n                onClick: testFunc,\n                onClose: testFunc,\n            },\n        })\n    })\n\n    it(\"'HIDE_NOTIFICATION' removes a notification from the store\", () => {\n        const store = createStore()\n\n        store.dispatch({\n            type: \"SHOW_NOTIFICATION\",\n            id: \"test_notification\",\n            title: \"title-test\",\n            detail: \"detail-test\",\n            level: \"info\",\n        })\n\n        store.dispatch({\n            type: \"HIDE_NOTIFICATION\",\n            id: \"test_notification\",\n        })\n\n        const state = store.getState()\n\n        assert.deepEqual(\n            state.notifications,\n            { test_notification: null },\n            \"Validate notification was removed\",\n        )\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/QuickOpen/FinderProcessTests.ts",
    "content": "/**\n * FinderProcessTests.ts\n */\n\nimport * as assert from \"assert\"\nimport { extractSplitData } from \"../../../src/Services/Search/FinderProcess\"\n\ndescribe(\"extractSplitData\", () => {\n    it(\"Splits the data by the delimiter\", () => {\n        const data = \"file1\\nfile2\\nfile3\\n\"\n        const delimiter = \"\\n\"\n        const lastRemnant = \"\"\n\n        const { splitData } = extractSplitData(data, delimiter, lastRemnant)\n\n        assert.equal(splitData.length, 3)\n    })\n\n    it(\"Ignores empty input\", () => {\n        const data = \"\"\n        const delimiter = \"\\n\"\n        const lastRemnant = \"\"\n\n        const { didExtract } = extractSplitData(data, delimiter, lastRemnant)\n\n        assert.equal(didExtract, false)\n    })\n\n    it(\"Returns a remnant if the data doesn't end with the delimiter\", () => {\n        const data = \"file1\\nfile2\"\n        const delimiter = \"\\n\"\n        const lastRemnant = \"\"\n\n        const { remnant, splitData } = extractSplitData(data, delimiter, lastRemnant)\n\n        assert.equal(remnant, \"file2\")\n        assert.equal(splitData.length, 1)\n    })\n\n    it(\"Returns an empty remnant if the data does end with the delimiter\", () => {\n        const data = \"file1\\nfile2\\n\"\n        const delimiter = \"\\n\"\n        const lastRemnant = \"\"\n\n        const { remnant } = extractSplitData(data, delimiter, lastRemnant)\n\n        assert.equal(remnant, \"\")\n    })\n\n    it(\"Prepends the last remnant if there was one\", () => {\n        const data = \"e1\\nfile2\\n\"\n        const delimiter = \"\\n\"\n        const lastRemnant = \"fil\"\n\n        const { splitData } = extractSplitData(data, delimiter, lastRemnant)\n\n        assert.equal(splitData.length, 2)\n        assert.equal(splitData[0], \"file1\")\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/QuickOpen/RegExFilterTests.ts",
    "content": "/**\n * RegExFilterTests.ts\n */\n\nimport * as assert from \"assert\"\nimport { createLetterCountDictionary } from \"../../../src/UI/components/HighlightText\"\nimport {\n    filter,\n    getHighlightsFromString,\n    processSearchTerm,\n} from \"./../../../src/Services/Menu/Filter/RegExFilter\"\n\ndescribe(\"processSearchTerm\", () => {\n    it(\"Correctly matches word.\", async () => {\n        const testString = \"src\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/test/index.ts\" },\n        ]\n\n        const result = processSearchTerm(testString, testList, false)\n\n        const expectedResult = [{ label: \"index.ts\", detail: \"browser/src/index.ts\" }]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly matches case-sensitive word.\", async () => {\n        const testString = \"SRC\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/SRC/index.ts\" },\n        ]\n\n        const result = processSearchTerm(testString, testList, true)\n\n        const expectedResult = [{ label: \"index.ts\", detail: \"browser/SRC/index.ts\" }]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly returns no matches.\", async () => {\n        const testString = \"zzz\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/test/index.ts\" },\n        ]\n\n        const result = processSearchTerm(testString, testList, false)\n\n        assert.deepEqual(result, [])\n    })\n})\n\ndescribe(\"regexFilter\", () => {\n    it(\"Correctly matches string.\", async () => {\n        const testString = \"index\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/index.ts\" },\n            { label: \"main.ts\", detail: \"browser/src/main.ts\" },\n            { label: \"index.ts\", detail: \"browser/test/index.ts\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the added highlights since they can be tested\n        // elsewhere.\n        result.forEach(r => {\n            delete r.detailHighlights\n            delete r.labelHighlights\n            delete r.score\n        })\n\n        const expectedResult = [\n            { label: \"index.ts\", detail: \"browser/src/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/test/index.ts\" },\n        ]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly splits and matches string.\", async () => {\n        const testString = \"index src\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/test/index.ts\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the added highlights since they can be tested\n        // elsewhere.\n        delete result[0].detailHighlights\n        delete result[0].labelHighlights\n        delete result[0].score\n\n        const expectedResult = [{ label: \"index.ts\", detail: \"browser/src/index.ts\" }]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly matches long split string.\", async () => {\n        const testString = \"index src service quickopen\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/services/menu/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen/index.ts\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the added highlights since they can be tested\n        // elsewhere.\n        delete result[0].detailHighlights\n        delete result[0].labelHighlights\n        delete result[0].score\n\n        const expectedResult = [\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen/index.ts\" },\n        ]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly doesn't match.\", async () => {\n        const testString = \"zzz\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/services/menu/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen/index.ts\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        assert.deepEqual(result, [])\n    })\n    it(\"Correctly matches split string in turn.\", async () => {\n        const testString = \"index main\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/services/config/index.ts\" },\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen/index.ts\" },\n            { label: \"main.ts\", detail: \"browser/src/services/menu/main.ts\" },\n        ]\n\n        // Should return no results, since the first term should restrict the second\n        // search to return no results.\n        const result = filter(testList, testString)\n\n        assert.deepEqual(result, [])\n    })\n})\n\ndescribe(\"getHighlightsFromString\", () => {\n    it(\"Correctly highlights a match when case is similar\", () => {\n        const match = \"foobar\"\n        const searchString = \"foob\"\n\n        const highlights = getHighlightsFromString(match, createLetterCountDictionary(searchString))\n\n        assert.deepEqual([0, 1, 2, 3], highlights)\n    })\n\n    it(\"Correctly highlights a search match when case is not similar (in case INSENSITIVE mode)\", () => {\n        const match = \"FooBar\"\n        const searchString = \"foob\"\n\n        const highlights = getHighlightsFromString(match, createLetterCountDictionary(searchString))\n\n        assert.deepEqual([0, 1, 2, 3], highlights)\n    })\n\n    it(\"Correctly highlights a search match when case is not similar (in case SENSITIVE mode)\", () => {\n        const match = \"FooBar\"\n        const searchString = \"foob\"\n\n        const highlights = getHighlightsFromString(\n            match,\n            createLetterCountDictionary(searchString),\n            true,\n        )\n\n        assert.deepEqual([1, 2], highlights)\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/QuickOpen/VSCodeFilterTests.ts",
    "content": "/**\n * VSCodeFilterTests.ts\n */\n\nimport * as assert from \"assert\"\nimport { ScorerCache } from \"../../../src/Services/Search/Scorer/QuickOpenScorer\"\nimport { filter, processSearchTerm } from \"./../../../src/Services/Menu/Filter/VSCodeFilter\"\n\ndescribe(\"processSearchTerm\", () => {\n    let cache: ScorerCache\n\n    beforeEach(() => {\n        cache = {}\n    })\n\n    it(\"Correctly matches word.\", async () => {\n        const testString = \"src\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src\" },\n            { label: \"index.ts\", detail: \"browser/test\" },\n        ]\n\n        const result = processSearchTerm(testString, testList, cache)\n        const filteredResult = result.filter(r => r.score !== 0)\n\n        // Remove the score since it can change if we updated the\n        // module. As long as its not 0 that is enough here.\n        assert.equal(result[0].score > 0, true)\n        delete result[0].score\n\n        const expectedResult = [\n            {\n                label: \"index.ts\",\n                labelHighlights: [] as number[],\n                detail: \"browser/src\",\n                detailHighlights: [8, 9, 10],\n            },\n        ]\n\n        assert.deepEqual(filteredResult, expectedResult)\n    })\n    it(\"Correctly score case-match higher\", async () => {\n        const testString = \"SRC\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src\" },\n            { label: \"index.ts\", detail: \"browser/SRC\" },\n        ]\n\n        const result = processSearchTerm(testString, testList, cache)\n\n        // Check the exact case match scores higher\n        const lowercase = result.find(r => r.detail === \"browser/src\")\n        const uppercase = result.find(r => r.detail === \"browser/SRC\")\n        assert.equal(uppercase.score > lowercase.score, true)\n\n        // Both should be highlighted though\n        assert.deepEqual(uppercase.detailHighlights, [8, 9, 10])\n        assert.deepEqual(lowercase.detailHighlights, [8, 9, 10])\n    })\n    it(\"Correctly returns no matches.\", async () => {\n        const testString = \"zzz\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src\" },\n            { label: \"index.ts\", detail: \"browser/test\" },\n        ]\n\n        const result = processSearchTerm(testString, testList, cache)\n        const filteredResult = result.filter(r => r.score !== 0)\n\n        assert.deepEqual(filteredResult, [])\n    })\n})\n\ndescribe(\"vsCodeFilter\", () => {\n    it(\"Correctly matches string.\", async () => {\n        const testString = \"index\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src\" },\n            { label: \"main.ts\", detail: \"browser/src\" },\n            { label: \"index.ts\", detail: \"browser/test\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the score since it can change if we updated the\n        // module.\n        // However, the score should be equal due to an exact match on both.\n        assert.equal(result[0].score === result[1].score, true)\n        delete result[0].score\n        delete result[1].score\n\n        const expectedResult = [\n            {\n                label: \"index.ts\",\n                labelHighlights: [0, 1, 2, 3, 4],\n                detail: \"browser/src\",\n                detailHighlights: [] as number[],\n            },\n            {\n                label: \"index.ts\",\n                labelHighlights: [0, 1, 2, 3, 4],\n                detail: \"browser/test\",\n                detailHighlights: [] as number[],\n            },\n        ]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly matches string with extension.\", async () => {\n        const testString = \"index.ts\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src\" },\n            { label: \"main.ts\", detail: \"browser/src\" },\n            { label: \"index.ts\", detail: \"browser/test\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the score since it can change if we updated the\n        // module.\n        // However, the score should be equal due to an exact match on both.\n        assert.equal(result[0].score === result[1].score, true)\n        delete result[0].score\n        delete result[1].score\n\n        const expectedResult = [\n            {\n                label: \"index.ts\",\n                labelHighlights: [0, 1, 2, 3, 4, 5, 6, 7],\n                detail: \"browser/src\",\n                detailHighlights: [] as number[],\n            },\n            {\n                label: \"index.ts\",\n                labelHighlights: [0, 1, 2, 3, 4, 5, 6, 7],\n                detail: \"browser/test\",\n                detailHighlights: [] as number[],\n            },\n        ]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly splits and matches string.\", async () => {\n        const testString = \"index src\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src\" },\n            { label: \"index.ts\", detail: \"browser/test\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the score since it can change if we updated the\n        // module. As long as its not 0 that is enough here.\n        assert.equal(result[0].score > 0, true)\n        delete result[0].score\n\n        const expectedResult = [\n            {\n                label: \"index.ts\",\n                labelHighlights: [0, 1, 2, 3, 4],\n                detail: \"browser/src\",\n                detailHighlights: [8, 9, 10],\n            },\n        ]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly matches long split string.\", async () => {\n        const testString = \"index src service quickopen\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/services/menu\" },\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Remove the score since it can change if we updated the\n        // module. As long as its not 0 that is enough here.\n        // Similarly, the highlights has been tested elsewhere,\n        // and its long here, so just check lengths.\n        assert.equal(result[0].score > 0, true)\n        assert.equal(result[0].labelHighlights.length === 5, true)\n        assert.equal(result[0].detailHighlights.length === 19, true)\n        delete result[0].score\n        delete result[0].labelHighlights\n        delete result[0].detailHighlights\n\n        const expectedResult = [{ label: \"index.ts\", detail: \"browser/src/services/quickopen\" }]\n\n        assert.deepEqual(result, expectedResult)\n    })\n    it(\"Correctly doesn't match.\", async () => {\n        const testString = \"zzz\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/services/menu\" },\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        assert.deepEqual(result, [])\n    })\n    it(\"Correctly matches split string in turn.\", async () => {\n        const testString = \"index main\"\n        const testList = [\n            { label: \"index.ts\", detail: \"browser/src/services/config\" },\n            { label: \"index.ts\", detail: \"browser/src/services/quickopen\" },\n            { label: \"main.ts\", detail: \"browser/src/services/menu\" },\n        ]\n\n        // Should return no results, since the first term should restrict the second\n        // search to return no results.\n        const result = filter(testList, testString)\n\n        assert.deepEqual(result, [])\n    })\n    it(\"Correctly sorts results for fuzzy match.\", async () => {\n        const testString = \"aBE\"\n        const testList = [\n            { label: \"BufferEditor.ts\", detail: \"packages/demo/src\" },\n            { label: \"BufferEditorContainer.ts\", detail: \"packages/demo/src\" },\n            { label: \"astBackedEditing.ts\", detail: \"packages/core/src\" },\n        ]\n\n        // All results match, but only the last has an exact match on aBE inside the file name.\n        const result = filter(testList, testString)\n\n        const be = result.find(r => r.label === \"BufferEditor.ts\")\n        const bec = result.find(r => r.label === \"BufferEditorContainer.ts\")\n        const abe = result.find(r => r.label === \"astBackedEditing.ts\")\n\n        // Therefore it should score the highest.\n        assert.equal(abe.score > be.score, true)\n        assert.equal(abe.score > bec.score, true)\n\n        // It should also be the first in the list\n        assert.deepEqual(result[0], abe)\n    })\n    it(\"Correctly sorts results for filtered search.\", async () => {\n        const testString = \"buffer test oni\"\n        const testList = [\n            { label: \"BufferEditor.ts\", detail: \"packages/demo/src\" },\n            { label: \"BufferEditorContainer.ts\", detail: \"packages/demo/src\" },\n            { label: \"BufferEditor.ts\", detail: \"packages/core/src\" },\n            { label: \"BufferEditor.ts\", detail: \"packages/core/test\" },\n            { label: \"BufferEditor.ts\", detail: \"packages/core/test/oni\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Should only match the last term\n        const best = result.find(r => r.detail === \"packages/core/test/oni\")\n        assert.deepEqual(result[0], best)\n        assert.equal(result.length, 1)\n    })\n    it(\"Correctly sorts results for shortest result on file name.\", async () => {\n        const testString = \"main\"\n        const testList = [\n            { label: \"main.tex\", detail: \"packages/core/src\" },\n            { label: \"main.tex\", detail: \"packages/core/test\" },\n            { label: \"main.tex\", detail: \"packages/core/test/oni\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Should prefer the short path\n        const best = result.find(r => r.detail === \"packages/core/src\")\n        const second = result.find(r => r.detail === \"packages/core/test\")\n        const third = result.find(r => r.detail === \"packages/core/test/oni\")\n\n        // Order should be as follows\n        assert.deepEqual(result[0], best)\n        assert.deepEqual(result[1], second)\n        assert.deepEqual(result[2], third)\n    })\n    it(\"Correctly sorts results for shortest result on path.\", async () => {\n        const testString = \"somepath\"\n        const testList = [\n            { label: \"fileA.ts\", detail: \"/some/path\" },\n            { label: \"fileB.ts\", detail: \"/some/path/longer\" },\n            { label: \"fileC.ts\", detail: \"packages/core/oni\" },\n        ]\n\n        const result = filter(testList, testString)\n\n        // Should prefer the short path\n        const best = result.find(r => r.label === \"fileA.ts\")\n        const second = result.find(r => r.label === \"fileB.ts\")\n\n        // Order should be as follows\n        assert.deepEqual(result[0], best)\n        assert.deepEqual(result[1], second)\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Sneak/SneakStoreTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createStore, ISneakInfo } from \"./../../../src/Services/Sneak/SneakStore\"\n\nconst createTestSneak = (\n    callback: () => void,\n    x: number = 1,\n    y: number = 1,\n    width: number = 10,\n    height: number = 10,\n): ISneakInfo => {\n    return {\n        rectangle: Oni.Shapes.Rectangle.create(x, y, width, height),\n        callback,\n    }\n}\n\ndescribe(\"SneakStore\", () => {\n    it(\"ADD_SNEAKS is ignored if not active\", () => {\n        const store = createStore()\n\n        const sneaks = [createTestSneak(null), createTestSneak(null)]\n\n        store.dispatch({\n            type: \"END\",\n        })\n\n        store.dispatch({\n            type: \"ADD_SNEAKS\",\n            sneaks,\n        })\n\n        const state = store.getState()\n\n        assert.deepEqual(state.sneaks, [])\n    })\n\n    it(\"Multiple ADD_SNEAKS actions are correctly labelled\", () => {\n        const store = createStore()\n\n        const sneaksRound1 = [createTestSneak(null), createTestSneak(null)]\n\n        store.dispatch({ type: \"START\", width: 100, height: 100 })\n        store.dispatch({\n            type: \"ADD_SNEAKS\",\n            sneaks: sneaksRound1,\n        })\n\n        const sneaksRound2 = [createTestSneak(null), createTestSneak(null)]\n\n        store.dispatch({\n            type: \"ADD_SNEAKS\",\n            sneaks: sneaksRound2,\n        })\n\n        const keys = store.getState().sneaks.map(s => s.triggerKeys)\n\n        assert.deepEqual(keys, [\"AA\", \"AB\", \"AC\", \"AD\"])\n    })\n\n    it(\"ADD_SNEAKS that are offscreen are not added\", () => {\n        const store = createStore()\n\n        const normalSneak = createTestSneak(null, 2, 2, 10, 10)\n        const offscreenSneak = createTestSneak(null, 101, 101, 10, 10)\n\n        const sneaksRound1 = [normalSneak, offscreenSneak]\n\n        store.dispatch({ type: \"START\", width: 100, height: 100 })\n        store.dispatch({\n            type: \"ADD_SNEAKS\",\n            sneaks: sneaksRound1,\n        })\n\n        const state = store.getState()\n        assert.strictEqual(state.sneaks.length, 1, \"Validate only one sneak was added\")\n        assert.strictEqual(state.sneaks[0].rectangle.x, 2, \"Validate the correct sneak was added\")\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Snippets/OniSnippetTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport { getLineCharacterFromOffset, OniSnippet } from \"./../../../src/Services/Snippets/OniSnippet\"\n\ndescribe(\"getLineCharacterFromOffset\", () => {\n    it(\"handles single line case\", () => {\n        const lines = [\"foo\"]\n\n        const result = getLineCharacterFromOffset(1, lines)\n        assert.deepEqual(result, { line: 0, character: 1 })\n    })\n\n    it(\"handles multi-line case\", () => {\n        const lines = [\"foo\", \"bar\"]\n\n        // '4' instead of '3' because of the new line...\n        const result = getLineCharacterFromOffset(4, lines)\n\n        assert.deepEqual(result, { line: 1, character: 0 })\n    })\n})\n\ndescribe(\"OniSnippet\", () => {\n    describe(\"getLines\", () => {\n        it(\"splits based on '\\\\n'\", () => {\n            const oniSnippet = new OniSnippet(\"foo\\nbar\")\n\n            const lines = oniSnippet.getLines()\n\n            assert.deepEqual(lines, [\"foo\", \"bar\"], \"Validate lines are split correctly\")\n        })\n\n        it(\"splits based on '\\\\r\\\\n'\", () => {\n            const oniSnippet = new OniSnippet(\"foo\\r\\nbar\")\n\n            const lines = oniSnippet.getLines()\n\n            assert.deepEqual(lines, [\"foo\", \"bar\"], \"Validate lines are split correctly\")\n        })\n    })\n\n    describe(\"getPlaceholders\", () => {\n        it(\"gets single placeholder\", () => {\n            const oniSnippet = new OniSnippet(\"foo${1:index}\") // tslint:disable-line\n\n            const placeholders = oniSnippet.getPlaceholders()\n\n            assert.deepEqual(placeholders[0], {\n                index: 1,\n                line: 0,\n                character: 3,\n                value: \"index\",\n                isFinalTabstop: false,\n            })\n        })\n\n        it(\"gets multiple placeholders on different lines\", () => {\n            const oniSnippet = new OniSnippet(\"foo${1:a}\\nbar${2:b}\") // tslint:disable-line\n\n            const placeholders = oniSnippet.getPlaceholders()\n\n            assert.deepEqual(placeholders[0], {\n                index: 1,\n                line: 0,\n                character: 3,\n                value: \"a\",\n                isFinalTabstop: false,\n            })\n\n            assert.deepEqual(placeholders[1], {\n                index: 2,\n                line: 1,\n                character: 3,\n                value: \"b\",\n                isFinalTabstop: false,\n            })\n        })\n\n        it(\"gets placeholder at end of line\", () => {\n            const oniSnippet = new OniSnippet(\"foo\\nbar${0}\") // tslint:disable-line\n            const placeholders = oniSnippet.getPlaceholders()\n\n            assert.deepEqual(placeholders[0], {\n                index: 0,\n                line: 1,\n                character: 3,\n                value: \"\",\n                isFinalTabstop: true,\n            })\n        })\n    })\n\n    describe(\"setPlaceholder\", () => {\n        it(\"replaces placeholder in multiple positions\", () => {\n            const oniSnippet = new OniSnippet(\"${1}${1}${1}\") // tslint:disable-line\n\n            oniSnippet.setPlaceholder(1, \"test\")\n\n            assert.deepEqual(oniSnippet.getLines(), [\"testtesttest\"])\n\n            oniSnippet.setPlaceholder(1, \"test2\")\n\n            assert.deepEqual(oniSnippet.getLines(), [\"test2test2test2\"])\n        })\n    })\n\n    describe(\"variableResolvers\", () => {\n        it(\"simple variable resolution\", () => {\n            const oniSnippet = new OniSnippet(\"$CURRENT_YEAR\", { resolve: variableName => \"2018\" })\n\n            assert.deepEqual(oniSnippet.getLines(), [\"2018\"])\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Snippets/SnippetCompletionProviderTests.ts",
    "content": "/**\n * SnippetCompletionProviderTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { SnippetCompletionProvider } from \"./../../../src/Services/Snippets/SnippetCompletionProvider\"\n\nexport class MockSnippetManager {\n    public get isSnippetActive(): boolean {\n        return false\n    }\n\n    public async getSnippetsForLanguage(language: string): Promise<Oni.Snippets.Snippet[]> {\n        const snippets: Oni.Snippets.Snippet[] = [\n            {\n                prefix: \"test\",\n                body: \"foobar\",\n                description: \"test snippet\",\n            },\n        ]\n        return snippets\n    }\n}\n\ndescribe(\"SnippetCompletionProviderTests\", () => {\n    it(\"returns empty array if no meets\", async () => {\n        const snippetManager: any = new MockSnippetManager()\n        const snippetCompletionProvider = new SnippetCompletionProvider(snippetManager)\n\n        const snippets = await snippetCompletionProvider.getCompletions({\n            language: \"test\",\n            filePath: \"test\",\n            line: 0,\n            column: 0,\n            meetCharacter: \"\",\n            textMateScopes: [],\n        })\n\n        assert.strictEqual(snippets.length, 0)\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Snippets/SnippetProviderTests.ts",
    "content": "/**\n * SnippetProviderTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\n\nimport { loadSnippetsFromText } from \"./../../../src/Services/Snippets/SnippetProvider\"\n\nconst ArraySnippet = `\n{\n    \"if\": {\n        \"prefix\": \"test\",\n        \"body\": [\n            \"line1\",\n            \"line2\"\n        ],\n        \"description\": \"Code snippet for an if statement\"\n    }\n}\n`\n\nconst SingleLineSnippet = `\n{\n    \"if\": {\n        \"prefix\": \"test\",\n        \"body\": \"line1\",\n        \"description\": \"Code snippet for an if statement\"\n    }\n}\n`\n\nconst TrailingCommaSnippet = `\n{\n    \"if\": {\n        \"prefix\": \"test\",\n        \"body\": [\"line1\"],\n        \"description\": \"Code snippet for an if statement\"\n    },\n}\n`\n\ndescribe(\"SnippetProviderTests\", () => {\n    describe(\"loadSnippetsFromText\", () => {\n        it(\"parses a basic snippet\", async () => {\n            const [parsedArraySnippet] = loadSnippetsFromText(ArraySnippet)\n\n            assert.strictEqual(\n                parsedArraySnippet.body,\n                \"line1\" + os.EOL + \"line2\",\n                \"Validate body was parsed correctly\",\n            )\n        })\n\n        it(\"parses single-line snippet\", async () => {\n            const [parsedSingleLineSnippet] = loadSnippetsFromText(SingleLineSnippet)\n            assert.strictEqual(\n                parsedSingleLineSnippet.body,\n                \"line1\",\n                \"Validate body was parsed correctly\",\n            )\n        })\n\n        it(\"parses snippet with trailing comma\", async () => {\n            const [parsedTrailingCommaSnippet] = loadSnippetsFromText(TrailingCommaSnippet)\n            assert.strictEqual(\n                parsedTrailingCommaSnippet.body,\n                \"line1\",\n                \"Validate body was parsed correctly\",\n            )\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Snippets/SnippetSessionTests.ts",
    "content": "/**\n * SnippetSessionTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport {\n    IMirrorCursorUpdateEvent,\n    SnippetSession,\n} from \"./../../../src/Services/Snippets/SnippetSession\"\n\nimport * as Mocks from \"./../../Mocks\"\n\n// tslint:disable no-invalid-template-strings\n\ndescribe(\"SnippetSession\", () => {\n    let mockEditor: Mocks.MockEditor\n    let mockBuffer: Mocks.MockBuffer\n    let snippetSession: SnippetSession\n\n    beforeEach(() => {\n        mockEditor = new Mocks.MockEditor()\n        mockBuffer = new Mocks.MockBuffer(\"typescript\", \"index.ts\", [\"\"])\n        mockEditor.simulateBufferEnter(mockBuffer)\n    })\n\n    describe(\"insertion\", () => {\n        it(\"inserts into empty line\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"foo\")\n\n            await snippetSession.start()\n\n            const [firstLine] = await mockBuffer.getLines(0, 1)\n\n            assert.strictEqual(firstLine, \"foo\")\n        })\n\n        it(\"inserts between characters\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"foo\")\n\n            // Add a line, and move cursor to line\n            mockBuffer.setLinesSync([\"someline\"])\n            mockBuffer.setCursorPosition(0, 4)\n\n            await snippetSession.start()\n\n            const [firstLine] = await mockBuffer.getLines(0, 1)\n\n            assert.strictEqual(firstLine, \"somefooline\")\n        })\n\n        it(\"matches existing whitespace for first line - 2 spaces\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"\\t\\tfoo\")\n\n            const indentationInfo = {\n                type: \"space\",\n                amount: 2,\n                indent: \"  \",\n            }\n\n            mockBuffer.setWhitespace(indentationInfo as any)\n            await snippetSession.start()\n\n            const [firstLine] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(firstLine, \"    foo\")\n        })\n\n        it(\"matches existing whitespace for first line - tabs\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"\\t\\tfoo\")\n\n            const indentationInfo = {\n                type: \"tab\",\n                amount: 0,\n                indent: \"\\t\",\n            }\n\n            mockBuffer.setWhitespace(indentationInfo as any)\n            await snippetSession.start()\n\n            const [firstLine] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(firstLine, \"\\t\\tfoo\")\n        })\n\n        it(\"mirrors cursor placeholders on insert\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"${1:test} ${1} ${1}\") // tslint:idsable-line\n\n            let lastEvent: IMirrorCursorUpdateEvent = null\n            snippetSession.onCursorMoved.subscribe(evt => {\n                lastEvent = evt\n            })\n\n            // Set visual mode so that the range is blockwise\n            mockEditor.simulateModeChange(\"visual\")\n\n            await snippetSession.start()\n\n            assert.ok(lastEvent !== null, \"Verify 'onCursorMoved' event was fired\")\n\n            const secondCursor = types.Range.create(0, 5, 0, 9)\n            const thirdCursor = types.Range.create(0, 10, 0, 14)\n\n            assert.deepEqual(lastEvent.cursors, [secondCursor, thirdCursor], \"Validate cursors\")\n        })\n    })\n\n    it(\"handles multiple lines\", async () => {\n        snippetSession = new SnippetSession(mockEditor as any, \"foo\\nbar\")\n\n        // Add a line, and move cursor to line\n        mockBuffer.setLinesSync([\"someline\"])\n        mockBuffer.setCursorPosition(0, 4)\n\n        await snippetSession.start()\n\n        const [firstLine, secondLine] = await mockBuffer.getLines(0, 2)\n\n        assert.strictEqual(firstLine, \"somefoo\")\n        assert.strictEqual(secondLine, \"barline\")\n    })\n\n    it(\"matches existing whitespace for whole snippet - 2 spaces\", async () => {\n        snippetSession = new SnippetSession(mockEditor as any, \"for {\\n\\tthing\\n}\")\n\n        const indentationInfo = {\n            type: \"space\",\n            amount: 2,\n            indent: \"  \",\n        }\n\n        mockBuffer.setWhitespace(indentationInfo as any)\n\n        // Add a line, and move cursor to line\n        mockBuffer.setLinesSync([\"  \"])\n        mockBuffer.setCursorPosition(0, 2)\n\n        await snippetSession.start()\n\n        const [firstLine, secondLine, thirdLine] = await mockBuffer.getLines(0, 3)\n\n        assert.strictEqual(firstLine, \"  for {\")\n        assert.strictEqual(secondLine, \"    thing\")\n        assert.strictEqual(thirdLine, \"  }\")\n    })\n\n    it(\"matches existing whitespace for whole snippet  - tabs\", async () => {\n        snippetSession = new SnippetSession(mockEditor as any, \"for {\\n\\tthing\\n}\")\n\n        const indentationInfo = {\n            type: \"tab\",\n            amount: 0,\n            indent: \"\\t\",\n        }\n\n        mockBuffer.setWhitespace(indentationInfo as any)\n\n        // Add a line, and move cursor to line\n        mockBuffer.setLinesSync([\"\\t\"])\n        mockBuffer.setCursorPosition(0, 1)\n\n        await snippetSession.start()\n\n        const [firstLine, secondLine, thirdLine] = await mockBuffer.getLines(0, 3)\n\n        assert.strictEqual(firstLine, \"\\tfor {\")\n        assert.strictEqual(secondLine, \"\\t\\tthing\")\n        assert.strictEqual(thirdLine, \"\\t}\")\n    })\n\n    it(\"highlights first placeholder\", async () => {\n        snippetSession = new SnippetSession(mockEditor as any, \"${0:test}\")\n\n        mockBuffer.setLinesSync([\"abc\"])\n        mockBuffer.setCursorPosition(0, 1)\n\n        await snippetSession.start()\n\n        const selection = await mockEditor.getSelection()\n\n        const expectedRange = types.Range.create(0, 1, 0, 4)\n        assert.strictEqual(selection.start.line, expectedRange.start.line)\n        assert.strictEqual(selection.start.character, expectedRange.start.character)\n        assert.strictEqual(selection.end.character, expectedRange.end.character)\n    })\n\n    describe(\"next placeholder\", () => {\n        it(\"highlights correct placeholder after calling nextPlaceholder\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"${1:test} ${0:test2}\")\n\n            await snippetSession.start()\n\n            await snippetSession.nextPlaceholder()\n\n            const selection = await mockEditor.getSelection()\n\n            const expectedRange = types.Range.create(0, 5, 0, 9)\n            assert.strictEqual(selection.start.line, expectedRange.start.line)\n            assert.strictEqual(selection.start.character, expectedRange.start.character)\n            assert.strictEqual(selection.end.character, expectedRange.end.character)\n        })\n\n        it(\"traverses order correctly, when placeholders are reversed\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"${0:test} ${1:test2}\")\n\n            await snippetSession.start()\n\n            let selection = await mockEditor.getSelection()\n\n            // Validate we are highlighting the _second_ item now\n            const expectedRange = types.Range.create(0, 5, 0, 9)\n            assert.strictEqual(selection.start.line, expectedRange.start.line)\n            assert.strictEqual(selection.start.character, expectedRange.start.character)\n            assert.strictEqual(selection.end.character, expectedRange.end.character)\n\n            await snippetSession.nextPlaceholder()\n            selection = await mockEditor.getSelection()\n\n            // Validate we are highlighting the _second_ item now\n            const secondItemRange = types.Range.create(0, 0, 0, 3)\n            assert.strictEqual(selection.start.line, secondItemRange.start.line)\n            assert.strictEqual(selection.start.character, secondItemRange.start.character)\n            assert.strictEqual(selection.end.character, secondItemRange.end.character)\n        })\n\n        it(\"traverses order correctly, when there are multiple placeholders with the same index\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"${1:test} ${0:test2} ${1}\")\n\n            const placeholder0Range = types.Range.create(0, 5, 0, 9)\n\n            await snippetSession.start() // Placeholder 1\n            await snippetSession.nextPlaceholder() // Placeholder 0\n\n            const selection = await mockEditor.getSelection()\n\n            assert.strictEqual(selection.start.line, placeholder0Range.start.line)\n            assert.strictEqual(selection.start.character, placeholder0Range.start.character)\n            assert.strictEqual(selection.end.character, placeholder0Range.end.character)\n        })\n\n        it(\"triggers finish event after last placeholder\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"${0:test}\")\n\n            let cancelHit = 0\n            snippetSession.onCancel.subscribe(() => {\n                cancelHit++\n            })\n\n            await snippetSession.start()\n            await snippetSession.nextPlaceholder()\n\n            assert.strictEqual(cancelHit, 1, \"Verify onCancel event was fired\")\n        })\n    })\n\n    describe(\"synchronizeUpdatedPlaceholders\", () => {\n        it(\"updates placeholders\", async () => {\n            snippetSession = new SnippetSession(mockEditor as any, \"${1:test} ${1} ${1}\")\n            await snippetSession.start()\n\n            // Validate\n            const [currentLine] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(currentLine, \"test test test\")\n\n            // Simulate typing in first entry\n            await mockEditor.setActiveBufferLine(0, \"test3 test test\")\n\n            await snippetSession.synchronizeUpdatedPlaceholders()\n\n            const [synchronizedLine] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(synchronizedLine, \"test3 test3 test3\")\n        })\n\n        it(\"updates placeholders when a placeholder becomes smaller\", async () => {\n            snippetSession = new SnippetSession(\n                mockEditor as any,\n                'import { ${1} } from \"${0:module}\"',\n            )\n            await snippetSession.start()\n\n            // Simulate shortening from \"module\" -> \"a\"\n            await mockEditor.setActiveBufferLine(0, 'import { } from \"a\"')\n\n            await snippetSession.synchronizeUpdatedPlaceholders()\n\n            const [synchronizedLine] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(synchronizedLine, 'import { } from \"a\"')\n\n            await snippetSession.synchronizeUpdatedPlaceholders()\n\n            const [synchronizedLine2] = await mockBuffer.getLines(0, 1)\n            assert.strictEqual(synchronizedLine2, 'import { } from \"a\"')\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Snippets/SnippetVariableResolverTests.ts",
    "content": "/**\n * SnippetVariableResolverTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { SnippetVariableResolver } from \"./../../../src/Services/Snippets\"\n\nimport { MockBuffer } from \"./../../Mocks\"\n\nconst createMockVariable = (name: string): any => ({\n    name,\n})\n\ndescribe(\"SnippetVariableResolverTests\", () => {\n    it(\"tests\", async () => {\n        const buffer = new MockBuffer(\"typescript\", \"test.ts\")\n        buffer.setCursorPosition(1, 1)\n\n        const variableResolver = new SnippetVariableResolver(buffer as any)\n\n        assert.strictEqual(variableResolver.resolve(createMockVariable(\"TM_FILENAME_BASE\")), \"test\")\n        assert.strictEqual(variableResolver.resolve(createMockVariable(\"TM_LINE_INDEX\")), \"1\")\n        assert.strictEqual(variableResolver.resolve(createMockVariable(\"TM_LINE_NUMBER\")), \"2\")\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/SyntaxHighlighting/SyntaxHighlightingReconcilerTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Mocks from \"./../../Mocks\"\n\nimport {\n    HighlightInfo,\n    ISyntaxHighlightLineInfo,\n    ISyntaxHighlightState,\n    SyntaxHighlightReconciler,\n} from \"./../../../src/Services/SyntaxHighlighting\"\n\nconst COLOR_BLACK = \"#000000\"\nconst COLOR_WHITE = \"#FFFFFF\"\n\ndescribe(\"SyntaxHighlightReconciler\", () => {\n    let syntaxHighlightReconciler: SyntaxHighlightReconciler\n    let mockTokenColors: Mocks.MockTokenColors\n    let mockEditor: Mocks.MockEditor\n    let mockBuffer: Mocks.MockBuffer\n\n    beforeEach(() => {\n        mockEditor = new Mocks.MockEditor()\n\n        mockTokenColors = new Mocks.MockTokenColors([\n            {\n                scope: [\"scope.test\"],\n                settings: {\n                    background: COLOR_BLACK,\n                    foreground: COLOR_WHITE,\n                    fontStyle: \"bold italic\",\n                },\n            },\n        ])\n\n        syntaxHighlightReconciler = new SyntaxHighlightReconciler(\n            mockEditor as any,\n            mockTokenColors as any,\n        )\n\n        mockBuffer = new Mocks.MockBuffer(\"javascript\", \"test.js\", [])\n        mockEditor.simulateBufferEnter(mockBuffer)\n    })\n\n    const createHighlightState = (lineNumber: number, line: string, tokenInfo: any[]) => {\n        const lineInfo: ISyntaxHighlightLineInfo = {\n            line,\n            ruleStack: null,\n            tokens: tokenInfo,\n            dirty: false,\n            version: 1,\n        }\n\n        const lines = {\n            [lineNumber]: lineInfo,\n        }\n\n        const testState: ISyntaxHighlightState = {\n            bufferToHighlights: {\n                [mockBuffer.id]: {\n                    bufferId: mockBuffer.id.toString(),\n                    language: mockBuffer.language,\n                    extension: null,\n                    topVisibleLine: 0,\n                    bottomVisibleLine: 100,\n                    insertModeLine: null,\n                    lines,\n                    version: 1,\n                },\n            },\n        }\n\n        return testState\n    }\n\n    it(\"sets tokens\", () => {\n        const tokenInfo = {\n            scopes: [\"scope.test\"],\n            range: types.Range.create(0, 0, 0, 5),\n        }\n\n        const testState = createHighlightState(0, null, [tokenInfo])\n\n        syntaxHighlightReconciler.update(testState)\n\n        const highlights = mockBuffer.mockHighlights.getHighlightsForLine(0)\n\n        const expectedHighlights: HighlightInfo[] = [\n            {\n                range: types.Range.create(0, 0, 0, 5),\n                tokenColor: {\n                    scope: [\"scope.test\"],\n                    settings: {\n                        background: COLOR_BLACK,\n                        foreground: COLOR_WHITE,\n                        fontStyle: \"bold italic\",\n                    },\n                },\n            },\n        ]\n\n        assert.deepEqual(\n            highlights,\n            expectedHighlights,\n            \"Validate highlightsAfterClearing are correct\",\n        )\n    })\n\n    it(\"uses latest info from insert mode\", () => {\n        // Simulate an empty state to start\n        const testState = createHighlightState(0, null, [])\n\n        syntaxHighlightReconciler.update(testState)\n\n        // And then we'll throw in an insert mode edit\n        const tokenInfo = {\n            scopes: [\"scope.test\"],\n            range: types.Range.create(0, 0, 0, 5),\n        }\n\n        const currentBufferInfo = testState.bufferToHighlights[mockBuffer.id]\n\n        const bufferInfoWithInsertUpdates = {\n            ...currentBufferInfo,\n            insertModeLine: {\n                lineNumber: 0,\n                version: 2,\n                info: {\n                    line: \"token\",\n                    ruleStack: null as any,\n                    tokens: [tokenInfo],\n                    dirty: false,\n                },\n            },\n        }\n\n        const updatedState: ISyntaxHighlightState = {\n            ...testState,\n            bufferToHighlights: {\n                ...testState.bufferToHighlights,\n                [mockBuffer.id]: bufferInfoWithInsertUpdates,\n            },\n        }\n\n        syntaxHighlightReconciler.update(updatedState)\n\n        const highlights = mockBuffer.mockHighlights.getHighlightsForLine(0)\n\n        const expectedHighlights: HighlightInfo[] = [\n            {\n                range: types.Range.create(0, 0, 0, 5),\n                tokenColor: {\n                    scope: [\"scope.test\"],\n                    settings: {\n                        background: COLOR_BLACK,\n                        foreground: COLOR_WHITE,\n                        fontStyle: \"bold italic\",\n                    },\n                },\n            },\n        ]\n\n        assert.deepEqual(\n            highlights,\n            expectedHighlights,\n            \"Validate tokens set in insert mode are correct\",\n        )\n    })\n\n    it(\"doesn't use insert mode line if version is earlier than latest tokenized version\", () => {\n        // Simulate an empty state to start\n        const testState = createHighlightState(0, null, [])\n\n        syntaxHighlightReconciler.update(testState)\n\n        // And then we'll throw in an insert mode edit\n        const tokenInfo = {\n            scopes: [\"scope.test\"],\n            range: types.Range.create(0, 0, 0, 5),\n        }\n\n        const currentBufferInfo = testState.bufferToHighlights[mockBuffer.id]\n\n        // Bump version past the insert mode line\n        currentBufferInfo.lines[0].version = 3\n\n        const bufferInfoWithInsertUpdates = {\n            ...currentBufferInfo,\n            insertModeLine: {\n                lineNumber: 0,\n                version: 2,\n                info: {\n                    line: \"token\",\n                    ruleStack: null as any,\n                    tokens: [tokenInfo],\n                    dirty: false,\n                },\n            },\n        }\n\n        const updatedState: ISyntaxHighlightState = {\n            ...testState,\n            bufferToHighlights: {\n                ...testState.bufferToHighlights,\n                [mockBuffer.id]: bufferInfoWithInsertUpdates,\n            },\n        }\n\n        syntaxHighlightReconciler.update(updatedState)\n\n        const highlights = mockBuffer.mockHighlights.getHighlightsForLine(0)\n\n        const expectedHighlights: HighlightInfo[] = []\n\n        assert.deepEqual(\n            highlights,\n            expectedHighlights,\n            \"Validate tokens set in insert mode are correct\",\n        )\n    })\n\n    it(\"clears tokens\", () => {\n        const tokenInfo = {\n            scopes: [\"scope.test\"],\n            range: types.Range.create(0, 0, 0, 5),\n        }\n\n        const testState = createHighlightState(0, null, [tokenInfo])\n\n        syntaxHighlightReconciler.update(testState)\n\n        // Now, clear the tokens out, and update again\n        const newState = createHighlightState(0, \"// new state\", [])\n        syntaxHighlightReconciler.update(newState)\n\n        const highlightsAfterClearing = mockBuffer.mockHighlights.getHighlightsForLine(0)\n        const expectedHighlights: HighlightInfo[] = []\n        assert.deepEqual(\n            highlightsAfterClearing,\n            expectedHighlights,\n            \"Validate highlightsAfterClearing are cleared\",\n        )\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/SyntaxHighlighting/SyntaxHighlightingReducerTests.ts",
    "content": "import * as assert from \"assert\"\r\n\r\nimport * as SyntaxHighlighting from \"./../../../src/Services/SyntaxHighlighting\"\r\n\r\ndescribe(\"SyntaxHighlightingReducer\", () => {\r\n    describe(\"linesReducer\", () => {\r\n        describe(\"SYNTAX_UPDATE_BUFFER\", () => {\r\n            it(\"sets buffer lines if they don't exist yet\", () => {\r\n                const originalState: SyntaxHighlighting.SyntaxHighlightLines = {}\r\n\r\n                const updateBufferAction: SyntaxHighlighting.ISyntaxHighlightAction = {\r\n                    type: \"SYNTAX_UPDATE_BUFFER\",\r\n                    extension: \"ts\",\r\n                    language: \"any\",\r\n                    bufferId: \"1\",\r\n                    lines: [\"line1\", \"line2\"],\r\n                    version: 1,\r\n                }\r\n\r\n                const newState = SyntaxHighlighting.linesReducer(originalState, updateBufferAction)\r\n\r\n                assert.deepEqual(newState[\"0\"], {\r\n                    line: \"line1\",\r\n                    dirty: true,\r\n                    ruleStack: null,\r\n                    tokens: [],\r\n                })\r\n\r\n                assert.deepEqual(newState[\"1\"], {\r\n                    line: \"line2\",\r\n                    dirty: true,\r\n                    ruleStack: null,\r\n                    tokens: [],\r\n                })\r\n            })\r\n\r\n            it(\"sets lines with a different buffer version to dirty\", () => {\r\n                const originalState: SyntaxHighlighting.SyntaxHighlightLines = {\r\n                    \"0\": {\r\n                        ruleStack: null,\r\n                        tokens: [],\r\n                        line: \"line1\",\r\n                        dirty: false,\r\n                        version: 1,\r\n                    },\r\n                    \"1\": {\r\n                        ruleStack: null,\r\n                        tokens: [],\r\n                        line: \"line2\",\r\n                        dirty: false,\r\n                        version: 0,\r\n                    },\r\n                }\r\n\r\n                const updateBufferAction: SyntaxHighlighting.ISyntaxHighlightAction = {\r\n                    type: \"SYNTAX_UPDATE_BUFFER\",\r\n                    extension: \"ts\",\r\n                    language: \"any\",\r\n                    bufferId: \"1\",\r\n                    lines: [\"line1\", \"line2_update\"],\r\n                    version: 1,\r\n                }\r\n\r\n                const newState = SyntaxHighlighting.linesReducer(originalState, updateBufferAction)\r\n\r\n                assert.deepEqual(newState[\"0\"], {\r\n                    ruleStack: null,\r\n                    tokens: [],\r\n                    line: \"line1\",\r\n                    dirty: false,\r\n                    version: 1,\r\n                })\r\n\r\n                assert.deepEqual(newState[\"1\"], {\r\n                    ruleStack: null,\r\n                    tokens: [],\r\n                    line: \"line2_update\",\r\n                    dirty: true,\r\n                    version: 0,\r\n                })\r\n            })\r\n        })\r\n    })\r\n})\r\n"
  },
  {
    "path": "browser/test/Services/TokenColorsTests.ts",
    "content": "/**\n * TokenColorsTest\n */\n\nimport * as assert from \"assert\"\n\nimport { TokenColors } from \"./../../src/Services/TokenColors\"\n\nimport { MockConfiguration, MockThemeLoader } from \"./../Mocks\"\n\nimport { DefaultTheme, ThemeManager } from \"./../../src/Services/Themes\"\n\ndescribe(\"TokenColors\", () => {\n    let mockConfiguration: MockConfiguration\n    let themeLoader: MockThemeLoader\n    let themeManager: ThemeManager\n\n    beforeEach(() => {\n        mockConfiguration = new MockConfiguration({\n            \"editor.tokenColors\": [{ scope: \"comment\", fontStyle: \"bold\" }],\n        })\n        themeLoader = new MockThemeLoader()\n        themeManager = new ThemeManager(themeLoader)\n        themeLoader.addTheme(\"testTheme\", DefaultTheme)\n    })\n\n    it(\"setting theme triggers onTokenColorsChanged event\", async () => {\n        const tokenColors = new TokenColors(mockConfiguration as any, themeManager)\n\n        let hitCount = 0\n        tokenColors.onTokenColorsChanged.subscribe(() => hitCount++)\n\n        await themeManager.setTheme(\"testTheme\")\n\n        assert.strictEqual(hitCount, 1, \"Validate onTokenColorsChanged was fired\")\n    })\n\n    it(\"if configuration is updated, but 'editor.tokenColors' isn't there, onTokenColorsChanged should not be triggered\", () => {\n        const tokenColors = new TokenColors(mockConfiguration as any, themeManager)\n\n        let hitCount = 0\n        tokenColors.onTokenColorsChanged.subscribe(() => hitCount++)\n\n        mockConfiguration.simulateConfigurationChangedEvent({ someConfigValue: 2 })\n        assert.strictEqual(hitCount, 0, \"Validate onTokenColorsChanged was fired\")\n    })\n\n    it(\"if 'editor.tokenColors' is updated from the config, onTokenColorsChanged event should be triggered\", () => {\n        const tokenColors = new TokenColors(mockConfiguration as any, themeManager)\n\n        let hitCount = 0\n        tokenColors.onTokenColorsChanged.subscribe(() => hitCount++)\n\n        mockConfiguration.simulateConfigurationChangedEvent({ \"editor.tokenColors\": [] })\n        assert.strictEqual(hitCount, 1, \"Validate onTokenColorsChanged was fired\")\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/TypingPredictionManagerTests.ts",
    "content": "/**\n * TypingPredictionManagerTests\n */\n\nimport * as assert from \"assert\"\n\nimport * as Neovim from \"./../../src/neovim\"\n\nimport {\n    ITypingPrediction,\n    TypingPredictionManager,\n} from \"./../../src/Services/TypingPredictionManager\"\nimport { MockScreen } from \"./../Mocks/neovim\"\n\ndescribe(\"TypingPredictionManager\", () => {\n    let mockScreen: MockScreen\n    let typingPredictionManager: TypingPredictionManager\n\n    beforeEach(() => {\n        mockScreen = new MockScreen()\n        mockScreen.backgroundColor = \"black\"\n        mockScreen.foregroundColor = \"white\"\n\n        typingPredictionManager = new TypingPredictionManager()\n        typingPredictionManager.enable()\n    })\n\n    it(\"Fires prediction changed event when character added\", () => {\n        mockScreen.cursorRow = 1\n        mockScreen.cursorColumn = 1\n        typingPredictionManager.setCursorPosition(mockScreen)\n\n        let callCount = 0\n        let lastResult: ITypingPrediction = null\n        typingPredictionManager.onPredictionsChanged.subscribe(pd => {\n            lastResult = pd\n            callCount++\n        })\n\n        typingPredictionManager.addPrediction(\"a\")\n\n        assert.strictEqual(callCount, 1, \"Verify prediction handler was fired exactly once\")\n        assert.strictEqual(\n            lastResult.backgroundColor,\n            \"black\",\n            \"Verify background color came from the screen\",\n        )\n        assert.strictEqual(\n            lastResult.foregroundColor,\n            \"white\",\n            \"Verify foreground color came from the screen\",\n        )\n        assert.strictEqual(\n            lastResult.predictedCursorColumn,\n            2,\n            \"Verify predictedCursorColumn is correct\",\n        )\n        assert.strictEqual(\n            lastResult.predictedCharacters.length,\n            1,\n            \"Verify there is exactly one prediction in lastResult\",\n        )\n        assert.deepEqual(\n            lastResult.predictedCharacters[0].character,\n            \"a\",\n            \"Verify predicted character is correct\",\n        )\n    })\n\n    it(\"#1039 - Doesn't add a prediction if it overlaps with an existing character on the screen\", () => {\n        mockScreen.cursorRow = 1\n        mockScreen.cursorColumn = 1\n        typingPredictionManager.setCursorPosition(mockScreen)\n\n        // Set a character at the third position, so that we can test the case where there\n        // is a single prediction, and a rejected prediction (because there is a character already on the cell)\n\n        const cell: Neovim.ICell = {\n            character: \"T\",\n            characterWidth: 1,\n        }\n\n        mockScreen.setCell(3 /* x: column*/, 1 /* y: row */, cell)\n\n        let callCount = 0\n        let lastResult: ITypingPrediction = null\n\n        typingPredictionManager.onPredictionsChanged.subscribe(pd => {\n            callCount++\n            lastResult = pd\n        })\n\n        typingPredictionManager.addPrediction(\"a\") // First prediction should succeed\n        typingPredictionManager.addPrediction(\"b\") // Second prediction doesn't succeed\n\n        assert.strictEqual(\n            callCount,\n            1,\n            \"Verify only a single call to the prediction handler was made\",\n        )\n        assert.strictEqual(\n            lastResult.predictedCharacters.length,\n            1,\n            \"Verify there is exactly one prediction in last result\",\n        )\n        assert.strictEqual(\n            lastResult.predictedCharacters[0].character,\n            \"a\",\n            \"Verify it was the first character entered that got predicted\",\n        )\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/WindowManager/LinearSplitProviderTests.ts",
    "content": "/**\n * LinearSplitProviderTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { ISplitInfo, ISplitLeaf, LinearSplitProvider } from \"./../../../src/Services/WindowManager\"\n\nimport { MockWindowSplit } from \"./../../Mocks\"\n\ndescribe(\"LinearSplitProviderTests\", () => {\n    let split1: MockWindowSplit\n    let split2: MockWindowSplit\n    // let split1Provider: SingleSplitProvider\n    // let split2Provider: SingleSplitProvider\n\n    let horizontalSplits: LinearSplitProvider\n    let verticalSplits: LinearSplitProvider\n\n    beforeEach(() => {\n        split1 = new MockWindowSplit()\n        split2 = new MockWindowSplit()\n\n        horizontalSplits = new LinearSplitProvider(\"horizontal\")\n        horizontalSplits.split(split1, \"vertical\")\n        horizontalSplits.split(split2, \"vertical\", split1)\n\n        verticalSplits = new LinearSplitProvider(\"vertical\")\n        verticalSplits.split(split1, \"horizontal\")\n        verticalSplits.split(split2, \"horizontal\")\n    })\n\n    it(\"contains returns true for included splits\", () => {\n        assert.strictEqual(true, horizontalSplits.contains(split1))\n        assert.strictEqual(true, horizontalSplits.contains(split2))\n    })\n\n    describe(\"move\", () => {\n        describe(\"horizontal split\", () => {\n            describe(\"null split\", () => {\n                it(\"moves in from left\", () => {\n                    // Because we're moving in from the left, split2 should be the active split\n                    const result = horizontalSplits.move(null, \"left\")\n                    assert.strictEqual(result, split2)\n                })\n\n                it(\"moves in from right\", () => {\n                    // Because we're moving in from the left, split2 should be the active split\n                    const result = horizontalSplits.move(null, \"right\")\n                    assert.strictEqual(result, split1)\n                })\n            })\n\n            describe(\"moving between splits\", () => {\n                it(\"moves left->right\", () => {\n                    const result = horizontalSplits.move(split1, \"right\")\n                    assert.strictEqual(result, split2)\n                })\n\n                it(\"moves right->left\", () => {\n                    const result = horizontalSplits.move(split1, \"right\")\n                    assert.strictEqual(result, split2)\n                })\n            })\n        })\n\n        describe(\"vertical split\", () => {\n            describe(\"null split\", () => {\n                it(\"handles up\", () => {\n                    // Because we're moving in from the bottom (upwards), split2 should be the active split\n                    const result = verticalSplits.move(null, \"up\")\n                    assert.strictEqual(result, split2)\n                })\n            })\n        })\n    })\n\n    describe(\"split\", () => {\n        it(\"creates nested split for different orientation\", () => {\n            const newSplit = new MockWindowSplit()\n            horizontalSplits.split(newSplit, \"vertical\", split2)\n        })\n\n        it(\"switches orientation if there is no child\", () => {\n            const splitProvider = new LinearSplitProvider(\"vertical\")\n            const newSplit = new MockWindowSplit()\n            splitProvider.split(newSplit, \"vertical\")\n\n            const state = splitProvider.getState()\n\n            assert.strictEqual(state.direction, \"horizontal\")\n        })\n\n        it(\"simple vertical split case\", () => {\n            const splitProvider = new LinearSplitProvider(\"horizontal\")\n\n            const mockSplit0 = new MockWindowSplit()\n            const mockSplit1 = new MockWindowSplit()\n\n            splitProvider.split(mockSplit0, \"vertical\")\n            splitProvider.split(mockSplit1, \"vertical\", mockSplit0)\n\n            const state = splitProvider.getState()\n\n            const splitState0: ISplitLeaf<MockWindowSplit> = state.splits[0] as any\n            const splitState1: ISplitLeaf<MockWindowSplit> = state.splits[1] as any\n\n            assert.strictEqual(state.direction, \"horizontal\")\n            assert.strictEqual(splitState0.contents, mockSplit0)\n            assert.strictEqual(splitState1.contents, mockSplit1)\n        })\n\n        it(\"simple horizontal split case\", () => {\n            const splitProvider = new LinearSplitProvider(\"vertical\")\n\n            const mockSplit0 = new MockWindowSplit()\n            const mockSplit1 = new MockWindowSplit()\n\n            splitProvider.split(mockSplit0, \"horizontal\")\n            splitProvider.split(mockSplit1, \"horizontal\", mockSplit0)\n\n            const state = splitProvider.getState()\n\n            const splitState0: ISplitLeaf<MockWindowSplit> = state.splits[0] as any\n            const splitState1: ISplitLeaf<MockWindowSplit> = state.splits[1] as any\n\n            assert.strictEqual(state.direction, \"vertical\")\n            assert.strictEqual(splitState0.contents, mockSplit0)\n            assert.strictEqual(splitState1.contents, mockSplit1)\n        })\n\n        // Test split arrangement like:\n        // 0|1\n        // ---\n        // 0|2\n        it(\"nested horizontal split case\", () => {\n            const splitProvider = new LinearSplitProvider(\"horizontal\")\n\n            const mockSplit0 = new MockWindowSplit()\n            const mockSplit1 = new MockWindowSplit()\n\n            splitProvider.split(mockSplit0, \"vertical\")\n            splitProvider.split(mockSplit1, \"vertical\", mockSplit0)\n\n            // Now, add a horizontal split against mockSplit1\n            const mockSplit2 = new MockWindowSplit()\n\n            splitProvider.split(mockSplit2, \"horizontal\", mockSplit1)\n\n            const state = splitProvider.getState()\n\n            assert.strictEqual(state.direction, \"horizontal\", \"Verify root is still horizontal\")\n            const verticalSplitLeft = state.splits[0] as ISplitLeaf<MockWindowSplit>\n            assert.strictEqual(verticalSplitLeft.type, \"Leaf\")\n            assert.strictEqual(verticalSplitLeft.contents, mockSplit0)\n\n            const verticalSplitRight = state.splits[1] as ISplitInfo<MockWindowSplit>\n            assert.strictEqual(verticalSplitRight.type, \"Split\")\n            assert.strictEqual(verticalSplitRight.direction, \"vertical\", \"Verify child is vertical\")\n\n            const verticalSplitRightChild0: ISplitLeaf<MockWindowSplit> = verticalSplitRight\n                .splits[0] as any\n            const verticalSplitRightChild1: ISplitLeaf<MockWindowSplit> = verticalSplitRight\n                .splits[1] as any\n\n            assert.strictEqual(verticalSplitRightChild0.contents, mockSplit1)\n            assert.strictEqual(verticalSplitRightChild1.contents, mockSplit2)\n        })\n\n        // Test split arrangement like:\n        // 0|2\n        // ---\n        // 111\n\n        it(\"nested vertical split case\", () => {\n            const splitProvider = new LinearSplitProvider(\"vertical\")\n\n            const mockSplit0 = new MockWindowSplit(\"mockSplit0\")\n            const mockSplit1 = new MockWindowSplit(\"mockSplit1\")\n\n            splitProvider.split(mockSplit0, \"horizontal\")\n            splitProvider.split(mockSplit1, \"horizontal\", mockSplit0)\n\n            // Now, add a horizontal split against mockSplit1\n            const mockSplit2 = new MockWindowSplit(\"mockSplit2\")\n\n            splitProvider.split(mockSplit2, \"vertical\", mockSplit0)\n\n            const state = splitProvider.getState()\n\n            assert.strictEqual(state.direction, \"vertical\", \"Verify root is still vertical\")\n\n            // Verify bottom leaf is as expected\n            const horizontalSplitBottom = state.splits[1] as ISplitLeaf<MockWindowSplit>\n            assert.strictEqual(horizontalSplitBottom.type, \"Leaf\")\n            assert.strictEqual(horizontalSplitBottom.contents, mockSplit1)\n\n            const horizontalSplitTop = state.splits[0] as ISplitInfo<MockWindowSplit>\n            assert.strictEqual(horizontalSplitTop.type, \"Split\")\n            assert.strictEqual(\n                horizontalSplitTop.direction,\n                \"horizontal\",\n                \"Verify child is horizontal\",\n            )\n\n            const horizontalSplitTopChild0: ISplitLeaf<MockWindowSplit> = horizontalSplitTop\n                .splits[0] as any\n            const horizontalSplitTopChild1: ISplitLeaf<MockWindowSplit> = horizontalSplitTop\n                .splits[1] as any\n\n            assert.strictEqual(horizontalSplitTopChild0.contents, mockSplit0)\n            assert.strictEqual(horizontalSplitTopChild1.contents, mockSplit2)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/WindowManager/RelationalSplitNavigatorTests.ts.ts",
    "content": "/**\n * RelationalSplitNavigatorTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport {\n    RelationalSplitNavigator,\n    SingleSplitProvider,\n} from \"./../../../src/Services/WindowManager\"\n\nimport { MockWindowSplit } from \"./../../Mocks\"\n\ndescribe(\"RelationalSplitNavigator\", () => {\n    let splitProvider: RelationalSplitNavigator\n    let split1: MockWindowSplit\n    let split2: MockWindowSplit\n    let split1Provider: SingleSplitProvider\n    let split2Provider: SingleSplitProvider\n\n    beforeEach(() => {\n        splitProvider = new RelationalSplitNavigator()\n        split1 = new MockWindowSplit()\n        split2 = new MockWindowSplit()\n        split1Provider = new SingleSplitProvider(split1)\n        split2Provider = new SingleSplitProvider(split2)\n    })\n\n    it(\"contains returns true/false\", () => {\n        // Make split2 'right' of split1\n        splitProvider.setRelationship(split1Provider, split2Provider, \"right\")\n\n        assert.strictEqual(true, splitProvider.contains(split1))\n        assert.strictEqual(true, splitProvider.contains(split2))\n        assert.strictEqual(false, splitProvider.contains(new MockWindowSplit()))\n    })\n\n    describe(\"move\", () => {\n        it(\"moves from one split to another\", () => {\n            // Make split2 'right' of split1\n            splitProvider.setRelationship(split1Provider, split2Provider, \"right\")\n\n            const forwardResult = splitProvider.move(split1, \"right\")\n            assert.strictEqual(forwardResult, split2, \"Move in the forward direction works\")\n\n            const inverseResult = splitProvider.move(split2, \"left\")\n            assert.strictEqual(inverseResult, split1, \"Move in the inverse direction works\")\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/WindowManager/WindowManagerTests.ts",
    "content": "/**\n * WindowManagerTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { ISplitInfo, WindowManager } from \"./../../../src/Services/WindowManager\"\nimport { MockWindowSplit } from \"./../../Mocks\"\n\ndescribe(\"WindowManagerTests\", () => {\n    let windowManager: WindowManager\n\n    beforeEach(() => {\n        windowManager = new WindowManager()\n    })\n\n    it(\"sends focus to previous split after closing\", async () => {\n        const split1 = new MockWindowSplit(\"window1\")\n        const split2 = new MockWindowSplit(\"window2\")\n        const split3 = new MockWindowSplit(\"window3\")\n\n        const handle1 = windowManager.createSplit(\"horizontal\", split1)\n        const handle2 = windowManager.createSplit(\"vertical\", split2, split1)\n\n        assert.strictEqual(windowManager.activeSplitHandle.id, handle2.id)\n\n        handle2.close()\n\n        assert.strictEqual(windowManager.activeSplitHandle.id, handle1.id)\n\n        const handle3 = windowManager.createSplit(\"horizontal\", split3, split1)\n        assert.strictEqual(windowManager.activeSplitHandle.id, handle3.id)\n\n        handle3.close()\n\n        assert.strictEqual(windowManager.activeSplitHandle.id, handle1.id)\n    })\n\n    it(\"can get split after a split is closed\", async () => {\n        const split1 = new MockWindowSplit(\"window1\")\n        const split2 = new MockWindowSplit(\"window2\")\n        const split3 = new MockWindowSplit(\"window3\")\n\n        windowManager.createSplit(\"horizontal\", split1)\n        const handle2 = windowManager.createSplit(\"vertical\", split2, split1)\n\n        handle2.close()\n\n        const handle3 = windowManager.createSplit(\"vertical\", split3, split1)\n\n        const handle = windowManager.getSplitHandle(split3)\n\n        assert.strictEqual(handle.id, handle3.id)\n    })\n\n    it(\"respects direction even if a reference split is not passed in\", async () => {\n        const split1 = new MockWindowSplit(\"window1\")\n        const split2 = new MockWindowSplit(\"window2\")\n\n        const handle1 = windowManager.createSplit(\"horizontal\", split1)\n        handle1.focus()\n\n        windowManager.createSplit(\"vertical\", split2, split1)\n\n        const splitRoot = windowManager.splitRoot\n\n        const firstChild = splitRoot.splits[0] as ISplitInfo<MockWindowSplit>\n\n        assert.strictEqual(firstChild.type, \"Split\")\n        assert.strictEqual(\n            firstChild.direction,\n            \"horizontal\",\n            \"Validate the splits are arranged horizontally (it's confusing... but this means they are vertical splits)\",\n        )\n        assert.strictEqual(firstChild.splits.length, 2, \"Validate both windows are in this split\")\n    })\n\n    it(\"#2147 - doesn't leave a split container after closing\", async () => {\n        const split1 = new MockWindowSplit(\"window1\")\n        const split2 = new MockWindowSplit(\"window2\")\n        const split3 = new MockWindowSplit(\"window3\")\n\n        windowManager.createSplit(\"horizontal\", split1)\n\n        const split2Handle = windowManager.createSplit(\"vertical\", split2, split1)\n        const split3Handle = windowManager.createSplit(\"horizontal\", split3, split2)\n\n        split2Handle.close()\n        split3Handle.close()\n\n        const splitRoot = windowManager.splitRoot\n        const firstChild = splitRoot.splits[0] as ISplitInfo<MockWindowSplit>\n\n        assert.strictEqual(splitRoot.type, \"Split\")\n        assert.strictEqual(splitRoot.direction, \"vertical\")\n        assert.strictEqual(splitRoot.splits.length, 1)\n\n        assert.strictEqual(firstChild.type, \"Split\")\n        assert.strictEqual(\n            firstChild.direction,\n            \"horizontal\",\n            \"Validate the splits are arranged horizontally (it's confusing... but this means they are vertical splits)\",\n        )\n        assert.strictEqual(\n            firstChild.splits.length,\n            1,\n            \"Validate there is only a single child in the 'horizontal' split.\",\n        )\n        assert.strictEqual(\n            firstChild.splits[0].type,\n            \"Leaf\",\n            \"Validate the child of the 'horizontal' split is a leaf node.\",\n        )\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/WindowManager/layoutFromSplitInfoTests.ts",
    "content": "/**\n * layoutFromSplitInfoTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { ISplitInfo, layoutFromSplitInfo } from \"./../../../src/Services/WindowManager\"\n\nimport { MockWindowSplit } from \"./../../Mocks\"\n\nconst resultFromSplitAndRect = (rectangle: Oni.Shapes.Rectangle, split: MockWindowSplit) => ({\n    split,\n    rectangle,\n})\n\ndescribe(\"layoutFromSplitInfoTests\", () => {\n    it(\"returns empty if no splits\", () => {\n        const emptySplit: ISplitInfo<MockWindowSplit> = {\n            type: \"Split\",\n            splits: [] as any,\n            direction: \"horizontal\",\n        }\n\n        const result = layoutFromSplitInfo(emptySplit, 100, 100)\n        assert.deepEqual(result, {})\n    })\n\n    it(\"gives full layout to a single item\", () => {\n        const split1 = new MockWindowSplit(\"windowSplit1\")\n        const split: ISplitInfo<MockWindowSplit> = {\n            type: \"Split\",\n            splits: [\n                {\n                    type: \"Leaf\",\n                    contents: split1,\n                },\n            ] as any,\n            direction: \"horizontal\",\n        }\n\n        const result = layoutFromSplitInfo(split, 100, 100)\n\n        assert.deepEqual(result, {\n            windowSplit1: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(0, 0, 100, 100),\n                split1,\n            ),\n        })\n    })\n\n    it(\"splits layout between two vertical items\", () => {\n        const split1 = new MockWindowSplit(\"windowSplit1\")\n        const split2 = new MockWindowSplit(\"windowSplit2\")\n        const split: ISplitInfo<MockWindowSplit> = {\n            type: \"Split\",\n            splits: [\n                {\n                    type: \"Leaf\",\n                    contents: split1,\n                },\n                {\n                    type: \"Leaf\",\n                    contents: split2,\n                },\n            ] as any,\n            direction: \"horizontal\",\n        }\n\n        const result = layoutFromSplitInfo(split, 100, 100)\n\n        assert.deepEqual(result, {\n            windowSplit1: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(0, 0, 50, 100),\n                split1,\n            ),\n            windowSplit2: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(50, 0, 50, 100),\n                split2,\n            ),\n        })\n    })\n\n    it(\"splits layout between two horizontal items\", () => {\n        const split1 = new MockWindowSplit(\"windowSplit1\")\n        const split2 = new MockWindowSplit(\"windowSplit2\")\n\n        const split: ISplitInfo<MockWindowSplit> = {\n            type: \"Split\",\n            splits: [\n                {\n                    type: \"Leaf\",\n                    contents: split1,\n                },\n                {\n                    type: \"Leaf\",\n                    contents: split2,\n                },\n            ] as any,\n            direction: \"vertical\",\n        }\n\n        const result = layoutFromSplitInfo(split, 100, 100)\n\n        assert.deepEqual(result, {\n            windowSplit1: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(0, 0, 100, 50),\n                split1,\n            ),\n            windowSplit2: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(0, 50, 100, 50),\n                split2,\n            ),\n        })\n    })\n\n    it(\"nested layout - splits between a vertical item, and then nested horizontal items\", () => {\n        // 1|2\n        // ---\n        // 1|3\n        const split1 = new MockWindowSplit(\"windowSplit1\")\n        const split2 = new MockWindowSplit(\"windowSplit2\")\n        const split3 = new MockWindowSplit(\"windowSplit3\")\n\n        const split: ISplitInfo<MockWindowSplit> = {\n            type: \"Split\",\n            splits: [\n                {\n                    type: \"Leaf\",\n                    contents: split1,\n                },\n                {\n                    type: \"Split\",\n                    splits: [\n                        {\n                            type: \"Leaf\",\n                            contents: split2,\n                        },\n                        {\n                            type: \"Leaf\",\n                            contents: split3,\n                        },\n                    ],\n                    direction: \"vertical\",\n                },\n            ] as any,\n            direction: \"horizontal\",\n        }\n\n        const result = layoutFromSplitInfo(split, 100, 100)\n\n        assert.deepEqual(result, {\n            windowSplit1: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(0, 0, 50, 100),\n                split1,\n            ),\n            windowSplit2: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(50, 0, 50, 50),\n                split2,\n            ),\n            windowSplit3: resultFromSplitAndRect(\n                Oni.Shapes.Rectangle.create(50, 50, 50, 50),\n                split3,\n            ),\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/Services/Workspace/WorkspaceConfigurationTests.ts",
    "content": "import * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport { WorkspaceConfiguration } from \"./../../../src/Services/Workspace\"\n\nimport * as Mocks from \"./../../Mocks\"\nimport * as TestHelpers from \"./../../TestHelpers\"\n\nconst MemoryFileSystem = require(\"memory-fs\") // tslint:disable-line\n\ndescribe(\"WorkspaceConfiguration\", () => {\n    let mockConfiguration: Mocks.MockConfiguration\n    let mockWorkspace: Mocks.MockWorkspace\n    let fileSystem: typeof fs | any\n\n    let workspaceWithNoConfigPath: string\n    let workspace1WithConfigPath: string\n    let workspace2WithConfigPath: string\n    let workspace1ConfigFilePath: string\n    let workspace2ConfigFilePath: string\n\n    beforeEach(() => {\n        fileSystem = new MemoryFileSystem()\n\n        workspaceWithNoConfigPath = path.join(TestHelpers.getRootDirectory(), \"workspace_noconfig\")\n        workspace1WithConfigPath = path.join(TestHelpers.getRootDirectory(), \"workspace1\")\n        workspace2WithConfigPath = path.join(TestHelpers.getRootDirectory(), \"workspace2\")\n\n        const dirsToCreate = [\n            workspace1WithConfigPath,\n            workspace2WithConfigPath,\n            workspaceWithNoConfigPath,\n        ]\n        dirsToCreate.forEach(p => fileSystem.mkdirpSync(p))\n\n        const createConfig = (workspacePath: string): string => {\n            const configFolderPath = path.join(workspacePath, \".oni\")\n            const configFilePath = path.join(configFolderPath, \"config.js\")\n            fileSystem.mkdirpSync(configFolderPath)\n            fileSystem.writeFileSync(configFilePath, \" \")\n            return configFilePath\n        }\n\n        workspace1ConfigFilePath = createConfig(workspace1WithConfigPath)\n        workspace2ConfigFilePath = createConfig(workspace2WithConfigPath)\n\n        mockConfiguration = new Mocks.MockConfiguration()\n        mockWorkspace = new Mocks.MockWorkspace()\n    })\n\n    it(\"setting directory before WorkspaceConfiguration is initialized loads configuration\", () => {\n        mockWorkspace.changeDirectory(workspace1WithConfigPath)\n\n        const ws = new WorkspaceConfiguration(mockConfiguration as any, mockWorkspace, fileSystem)\n        assert.strictEqual(\n            ws.activeWorkspaceConfiguration,\n            workspace1ConfigFilePath,\n            \"Validate correct workspace is picked up\",\n        )\n        assert.deepEqual(\n            mockConfiguration.currentConfigurationFiles,\n            [workspace1ConfigFilePath],\n            \"Validate configuration file was added\",\n        )\n    })\n\n    it(\"changing from one workspace to another causes first config to be removed\", () => {\n        const ws = new WorkspaceConfiguration(mockConfiguration as any, mockWorkspace, fileSystem)\n\n        mockWorkspace.changeDirectory(workspace1WithConfigPath)\n        mockWorkspace.changeDirectory(workspace2WithConfigPath)\n\n        assert.strictEqual(\n            ws.activeWorkspaceConfiguration,\n            workspace2ConfigFilePath,\n            \"Validate correct workspace is picked up\",\n        )\n        assert.deepEqual(\n            mockConfiguration.currentConfigurationFiles,\n            [workspace2ConfigFilePath],\n            \"Validate configuration file was added\",\n        )\n    })\n\n    it(\"changing directory causes new config to be loaded\", () => {\n        const ws = new WorkspaceConfiguration(mockConfiguration as any, mockWorkspace, fileSystem)\n\n        mockWorkspace.changeDirectory(workspace1WithConfigPath)\n\n        assert.strictEqual(\n            ws.activeWorkspaceConfiguration,\n            workspace1ConfigFilePath,\n            \"Validate correct workspace is picked up\",\n        )\n        assert.deepEqual(\n            mockConfiguration.currentConfigurationFiles,\n            [workspace1ConfigFilePath],\n            \"Validate configuration file was added\",\n        )\n    })\n})\n"
  },
  {
    "path": "browser/test/Tabs/TabsTest.tsx",
    "content": "import * as assert from \"assert\"\nimport * as path from \"path\"\nimport { checkDuplicate, getTabName } from \"./../../src/UI/components/Tabs\"\n\ndescribe(\"Tab bar utility function tests\", () => {\n    describe(\"Array duplicates check\", () => {\n        it(\"Should return a true if there is a duplicate in an array\", () => {\n            const testArray = [\"/folder/index.js\", \"/folderTwo/index.js\"]\n            const isDuplicate = checkDuplicate(\"index.js\", testArray)\n            assert.ok(isDuplicate)\n        })\n        it(\"Should return a false if there is not a duplicate in an array\", () => {\n            const testArray = [\"/folder/index.js\", \"/folderTwo/apple.js\"]\n            const isDuplicate = checkDuplicate(\"index.js\", testArray)\n            assert.ok(!isDuplicate)\n        })\n    })\n    describe(\"Get tab name function should return a longer name if duplicates present\", () => {\n        const sep = path.sep\n        it(\"Should return a only a filename if there are no duplicates\", () => {\n            const testArray = [`${sep}folder${sep}index.js`, `${sep}folderTwo${sep}apple.js`]\n            const isDuplicate = checkDuplicate(\"index.js\", testArray)\n            const name = getTabName(`${sep}folder${sep}index.js`, isDuplicate)\n            assert.ok(name === \"index.js\")\n        })\n        it(\"Should return a folder and a filename if there are duplicates\", () => {\n            const testArray = [`${sep}folder${sep}index.js`, `${sep}folderTwo${sep}index.js`]\n            const isDuplicate = checkDuplicate(`index.js`, testArray)\n            const name = getTabName(`${sep}folder${sep}index.js`, isDuplicate)\n            assert.ok(name === `folder${sep}index.js`)\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/TestHelpers.ts",
    "content": "/**\n * TestHelpers.ts\n *\n * Set of utilities to assist with testing. Shim around some of the utilities we hook up in `testHelpers.js`\n */\n\n/**\n * runAllTimers executes all pending clocks - including intervals, timeouts, and requestAnimationFrames\n */\nexport const runAllTimers = (): void => {\n    global[\"clock\"].runAll() // tslint:disable-line\n}\n\nexport const tick = (timeInMilliseconds: number): void => {\n    global[\"clock\"].tick(timeInMilliseconds) // tslint:disable-line\n}\n\n/**\n * Wait for pending promise calls - needed for any code paths that have an asynchronous timer or use `Promise.resolve`\n */\nexport const waitForPromiseResolution = async (): Promise<void> => {\n    await global[\"waitForPromiseResolution\"]() // tslint:disable-line\n}\n\nexport const waitForAllAsyncOperations = async (): Promise<void> => {\n    await waitForPromiseResolution()\n    runAllTimers()\n}\n\nimport * as os from \"os\"\n\nexport const getRootDirectory = (): string => {\n    const top = os.platform() === \"win32\" ? \"C:/\" : \"/top\"\n    return top\n}\n"
  },
  {
    "path": "browser/test/UtilityTests.ts",
    "content": "import * as assert from \"assert\"\n\nimport * as rxjs from \"rxjs\"\n\nimport * as Utility from \"./../src/Utility\"\n\ninterface PromiseInfo {\n    resolve: (val: any) => void\n    reject: (err: Error) => void\n}\ninterface PromiseCreationResult {\n    info: PromiseInfo[]\n    inputs: any[]\n    promiseCreator: (input: any) => Promise<any>\n}\nconst createPromiseFunction = (): PromiseCreationResult => {\n    const info: any[] = []\n    const inputs: any[] = []\n\n    const promiseCreator = (input: any) => {\n        inputs.push(input)\n\n        return new Promise((resolve, reject) => {\n            info.push({ resolve, reject })\n        })\n    }\n\n    return {\n        info,\n        inputs,\n        promiseCreator,\n    }\n}\n\ndescribe(\"Utility\", () => {\n    describe(\"ignoreWhilePendingPromise\", () => {\n        let subject: rxjs.Subject<any>\n\n        beforeEach(() => {\n            subject = new rxjs.Subject()\n        })\n\n        it(\"Executes promise function in response to observable input\", () => {\n            const promiseFunction = createPromiseFunction()\n\n            const outputObservable$ = Utility.ignoreWhilePendingPromise(\n                subject,\n                promiseFunction.promiseCreator,\n            )\n\n            const outputs: any[] = []\n            outputObservable$.subscribe(val => {\n                outputs.push(val)\n            })\n\n            // Resolve the promise that gets fired as a result of subject triggered\n            subject.next(5)\n            promiseFunction.info[0].resolve(\"a\")\n\n            return outputObservable$\n                .take(1)\n                .toPromise()\n                .then(() => {\n                    assert.deepEqual(promiseFunction.inputs, [5])\n                    assert.deepEqual(outputs, [\"a\"])\n                })\n        })\n\n        it(\"Does not dispatch promise function while previous is still pending\", () => {\n            const promiseFunction = createPromiseFunction()\n\n            const outputObservable$ = Utility.ignoreWhilePendingPromise(\n                subject,\n                promiseFunction.promiseCreator,\n            )\n\n            const outputs: any[] = []\n            outputObservable$.subscribe(val => {\n                outputs.push(val)\n            })\n\n            // Bring in multiple inputs\n            subject.next(5)\n            subject.next(6)\n            subject.next(7)\n            subject.next(8)\n            promiseFunction.info[0].resolve(\"a\")\n\n            return outputObservable$\n                .take(1)\n                .toPromise()\n                .then(() => {\n                    // Only 5 & 7 should've been dispatched to the function,\n                    // because the observable should've been held\n                    // while the first promise was in flight,\n                    // and 8 would've been dispatched when the promise for 5 was completed.\n                    assert.deepEqual(promiseFunction.inputs, [5, 8])\n                    assert.deepEqual(outputs, [\"a\"])\n                })\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/neovim/NeovimBufferUpdateManagerTests.ts",
    "content": "/**\n * NeovimBufferUpdateManagerTests.ts\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\n\nimport { EventContext } from \"./../../src/neovim\"\nimport {\n    INeovimBufferUpdate,\n    NeovimBufferUpdateManager,\n} from \"./../../src/neovim/NeovimBufferUpdateManager\"\n\nimport { MockConfiguration, MockNeovimInstance } from \"./../Mocks\"\nimport { waitForAllAsyncOperations } from \"./../TestHelpers\"\n\nconst createTestEventContext = (bufferNumber: number, bufferTotalLines: number): EventContext => {\n    return {\n        bufferNumber,\n        bufferTotalLines,\n    } as any\n}\n\ndescribe(\"NeovimBufferUpdateManagerTests\", () => {\n    let configuration: MockConfiguration = null\n    let neovimInstance: MockNeovimInstance = null\n    let bufferUpdateManager: NeovimBufferUpdateManager = null\n\n    beforeEach(() => {\n        configuration = new MockConfiguration({ \"editor.maxLinesForLanguageServices\": 1000 })\n        neovimInstance = new MockNeovimInstance()\n\n        bufferUpdateManager = new NeovimBufferUpdateManager(\n            configuration as any,\n            neovimInstance as any,\n        )\n    })\n\n    it(\"dispatches when there is a full update\", async () => {\n        const evt = createTestEventContext(1, 100)\n        bufferUpdateManager.notifyFullBufferUpdate(evt)\n\n        let hitCount = 0\n        bufferUpdateManager.onBufferUpdate.subscribe(() => hitCount++)\n\n        assert.strictEqual(neovimInstance.getPendingRequests().length, 1)\n\n        neovimInstance.flushFirstRequest([\"a\", \"b\", \"c\"])\n        await waitForAllAsyncOperations()\n\n        assert.strictEqual(hitCount, 1, \"Validate 'onBufferUpdate' was dispatched\")\n    })\n\n    it(\"debounces multiple full updates, while a request is pending\", async () => {\n        let hitCount = 0\n        let lastResult: INeovimBufferUpdate = null\n        bufferUpdateManager.onBufferUpdate.subscribe(result => {\n            lastResult = result\n            hitCount++\n        })\n\n        // Send five requests\n        const evt1 = createTestEventContext(1, 100)\n        const evt2 = createTestEventContext(1, 101)\n        const evt3 = createTestEventContext(1, 102)\n        const evt4 = createTestEventContext(1, 104)\n        const evt5 = createTestEventContext(1, 105)\n\n        bufferUpdateManager.notifyFullBufferUpdate(evt1)\n        bufferUpdateManager.notifyFullBufferUpdate(evt2)\n        bufferUpdateManager.notifyFullBufferUpdate(evt3)\n        bufferUpdateManager.notifyFullBufferUpdate(evt4)\n        bufferUpdateManager.notifyFullBufferUpdate(evt5)\n\n        // Validate there is only a _single_ request queued up\n        assert.strictEqual(neovimInstance.getPendingRequests().length, 1)\n\n        neovimInstance.flushFirstRequest([\"a\", \"b\", \"c\"])\n        await waitForAllAsyncOperations()\n\n        // Validate there is now _another_ request queued up\n        assert.strictEqual(neovimInstance.getPendingRequests().length, 1)\n        const firstRequest = neovimInstance.getPendingRequests()[0]\n\n        // Validate the request corresponds to the last item\n        assert.strictEqual(firstRequest.args[2] /* 3rd parameter - totalBufferLines */, 105)\n\n        neovimInstance.flushFirstRequest([\"d\", \"e\", \"f\"])\n        await waitForAllAsyncOperations()\n\n        assert.strictEqual(\n            hitCount,\n            2,\n            \"Validate the onBufferUpdate event was dispatched twice - first on the leading and second on the trailing call\",\n        )\n        assert.strictEqual(lastResult.contentChanges[0].text, [\"d\", \"e\", \"f\"].join(os.EOL))\n\n        // Validate there are no additional pending requests\n        assert.strictEqual(neovimInstance.getPendingRequests().length, 0)\n    })\n})\n"
  },
  {
    "path": "browser/test/neovim/NeovimMarksTests.ts",
    "content": "/**\n * NeovimMarksTest.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { parseMarkLine } from \"./../../src/neovim/NeovimMarks\"\n\ndescribe(\"NeovimMarks\", () => {\n    describe(\"parseMarkLine\", () => {\n        it(\"parses a simple line\", () => {\n            const line = \"    A   1 10 some Text\"\n\n            const markInfo = parseMarkLine(line)\n\n            assert.strictEqual(markInfo.line, 1)\n            assert.strictEqual(markInfo.column, 10)\n            assert.strictEqual(markInfo.mark, \"A\")\n            assert.strictEqual(markInfo.global, true)\n            assert.strictEqual(markInfo.text, \"some Text\")\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/neovim/NeovimTokenColorSynchronizerTests.ts",
    "content": "/**\n * NeovimTokenColorSynchronizerTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { NeovimTokenColorSynchronizer } from \"./../../src/neovim/NeovimTokenColorSynchronizer\"\nimport { TokenColor } from \"./../../src/Services/TokenColors\"\n\nimport { MockNeovimInstance } from \"./../Mocks/neovim\"\n\nconst createTokenColor = (...scope: string[]): TokenColor => ({\n    scope,\n    settings: {\n        foreground: \"#FFFFFF\",\n        background: \"#FF0000\",\n        fontStyle: null,\n    },\n})\n\ndescribe(\"NeovimTokenColorSynchronizer\", () => {\n    let neovimInstance: MockNeovimInstance\n    let tokenColorSynchronizer: NeovimTokenColorSynchronizer\n\n    beforeEach(() => {\n        neovimInstance = new MockNeovimInstance()\n        tokenColorSynchronizer = new NeovimTokenColorSynchronizer(neovimInstance as any)\n    })\n\n    describe(\"synchronizeTokenColors\", () => {\n        it(\"adds token color if it doesn't exist\", async () => {\n            const color = createTokenColor(\"test.scope\")\n            const promise = tokenColorSynchronizer.synchronizeTokenColors([color])\n            const pendingRequests = neovimInstance.getPendingRequests()\n\n            const firstRequest = pendingRequests[0]\n            assert.strictEqual(firstRequest.requestName, \"nvim_call_atomic\")\n\n            const subRequests = pendingRequests[0].args\n            assert.strictEqual(subRequests.length, 1)\n\n            const [subRequestName, subRequestArgs] = subRequests[0][0]\n\n            assert.strictEqual(subRequestName, \"nvim_command\")\n            assert.ok(subRequestArgs[0].indexOf(\"guibg=#FF0000\"))\n            assert.ok(subRequestArgs[0].indexOf(\"guifg=#FFFFFF\"))\n\n            neovimInstance.flushPendingRequests()\n\n            await promise\n        })\n\n        it(\"doesn't add token color if it already exists\", async () => {\n            // Add a token color...\n            const color = createTokenColor(\"test.scope\")\n            const promise = tokenColorSynchronizer.synchronizeTokenColors([color])\n\n            neovimInstance.flushPendingRequests()\n            await promise\n\n            // ...now add it again\n            const promise2 = tokenColorSynchronizer.synchronizeTokenColors([color])\n\n            // Validate there were no pending requests\n            assert.strictEqual(neovimInstance.getPendingRequests().length, 0)\n            await promise2\n        })\n    })\n})\n"
  },
  {
    "path": "browser/test/neovim/ScreenWithPredictionsTest.ts",
    "content": "/**\n * NeovimTokenColorSynchronizerTests.ts\n */\n\nimport * as assert from \"assert\"\n\nimport { ScreenWithPredictions } from \"./../../src/neovim/ScreenWithPredictions\"\nimport { ITypingPrediction } from \"./../../src/Services/TypingPredictionManager\"\n\nimport { MockConfiguration } from \"./../Mocks\"\nimport { MockScreen } from \"./../Mocks/neovim\"\n\nconst createTypingPredictions = (\n    predictedCursorColumn: number,\n    backgroundColor: string,\n    foregroundColor: string,\n    predictedCharacters: string[],\n): ITypingPrediction => ({\n    predictedCursorColumn,\n    backgroundColor,\n    foregroundColor,\n    predictedCharacters: predictedCharacters.map((s, idx) => ({ id: idx, character: s })),\n})\n\nconst createCell = (character: string) => ({\n    backgroundColor: \"purple\",\n    foregroundColor: \"gray\",\n    character,\n    characterWidth: 1,\n})\n\ndescribe(\"ScreenWithPredictions\", () => {\n    let mockScreen: MockScreen\n    let predictedScreen: ScreenWithPredictions\n    let mockConfiguration: MockConfiguration\n\n    beforeEach(() => {\n        mockScreen = new MockScreen()\n        mockConfiguration = new MockConfiguration()\n        predictedScreen = new ScreenWithPredictions(mockScreen, mockConfiguration as any)\n    })\n\n    describe(\"updatePredictions\", () => {\n        it(\"updates cell when a prediction is available\", async () => {\n            mockScreen.setCell(0, 0, createCell(\"a\"))\n            predictedScreen.updatePredictions(\n                createTypingPredictions(3, \"yellow\", \"green\", [\"b\", \"c\"]),\n                0,\n            )\n\n            const firstPredictedCell = predictedScreen.getCell(1, 0)\n            const secondPredictedCell = predictedScreen.getCell(2, 0)\n            assert.strictEqual(firstPredictedCell.character, \"b\")\n            assert.strictEqual(secondPredictedCell.character, \"c\")\n        })\n\n        it(\"highlights cell when 'debug.showTypingPrediction' is enabled\", () => {\n            mockConfiguration.setValue(\"debug.showTypingPrediction\", true)\n            mockScreen.setCell(0, 0, createCell(\"a\"))\n            predictedScreen.updatePredictions(\n                createTypingPredictions(2, \"yellow\", \"green\", [\"b\"]),\n                0,\n            )\n\n            const predictedCell = predictedScreen.getCell(1, 0)\n            // Validate colos are overridden\n            assert.strictEqual(predictedCell.backgroundColor, \"red\")\n            assert.strictEqual(predictedCell.foregroundColor, \"white\")\n        })\n    })\n})\n"
  },
  {
    "path": "browser/testCoverageReporter.js",
    "content": "/**\n * testCoverageReporter.js\n *\n * Reporter for mocha to output the code coverage results\n */\n\nconst fs = require(\"fs\")\nconst path = require(\"path\")\nconst mkdirp = require(\"mkdirp\")\n\nconst istanbulAPI = require(\"istanbul-api\")\nconst libCoverage = require(\"istanbul-lib-coverage\")\n\nfunction Coverage(runner) {\n    runner.on(\"end\", () => {\n        const mainReporter = istanbulAPI.createReporter()\n        const coverageMap = libCoverage.createCoverageMap()\n        console.log(\"Merging coverage map...\")\n        coverageMap.merge(window.__coverage__ || {})\n        console.log(\"Merging coverage map complete\")\n\n        console.log(\"Adding reporters...\")\n        mainReporter.addAll([\"text\", \"json\", \"html\", \"lcov\"])\n        console.log(\"Writing code coverage map...\")\n        mainReporter.write(coverageMap, {})\n        console.log(\"Complete!\")\n    })\n}\n\nmodule.exports = Coverage\n"
  },
  {
    "path": "browser/testHelpers.js",
    "content": "const Module = require(\"module\")\nconst originalRequire = Module.prototype.require\n\nif (global.window) {\n    const originalSetTimeout = global.setTimeout\n\n    const lolex = require(\"lolex\")\n    const clock = lolex.install()\n    // const createMockRaf = require(\"mock-raf\")\n    // const mockRaf = createMockRaf()\n\n    // sinon.stub(window, \"requestAnimationFrame\", mockRaf.raf)\n\n    // global.mockRaf = mockRaf\n\n    console.log(\"clock installed\")\n\n    global.clock = clock\n\n    global.waitForPromiseResolution = promise => {\n        return new Promise(res => {\n            originalSetTimeout(() => res(), 1)\n        })\n    }\n}\n\nconst shouldUseCodeCoverage = !!process.env[\"ONI_CCOV\"]\nconsole.log(\"Code coverage: \" + shouldUseCodeCoverage)\n\nconsole.log(\"Hooking require, so that we don't import .less files\")\nModule.prototype.require = function(moduleName, ...args) {\n    if (moduleName.indexOf(\".less\") >= 0) {\n        console.warn(\"Skipping require for: \" + moduleName)\n        return\n    }\n\n    // If ccov is enabled, we should pull the file from the 'ccov' folder created by `npm run ccov:instrument`\n    // Idea adapted from:\n    // https://github.com/MarshallOfSound/Google-Play-Music-Desktop-Player-UNOFFICIAL-/commit/1b2055b286f1f296c0d48dec714224c14acb3c34\n    const ccovFile = shouldUseCodeCoverage\n        ? moduleName.replace(\"../src/\", \"../src_ccov/\")\n        : moduleName\n    return originalRequire.call(this, ccovFile, ...args)\n}\n"
  },
  {
    "path": "browser/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowUnreachableCode\": false,\n        \"allowUnusedLabels\": false,\n        \"experimentalDecorators\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"module\": \"esnext\",\n        \"moduleResolution\": \"node\",\n        \"newLine\": \"LF\",\n        \"noEmitOnError\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"noImplicitAny\": true,\n        \"noImplicitReturns\": true,\n        \"noImplicitThis\": true,\n        \"noUnusedLocals\": true,\n        \"outDir\": \"../lib_test/browser\",\n        \"pretty\": true,\n        \"removeComments\": true,\n        \"rootDir\": \".\",\n        \"skipLibCheck\": true,\n        \"strictNullChecks\": false,\n        \"suppressImplicitAnyIndexErrors\": true,\n        \"target\": \"es2015\",\n        \"sourceMap\": true,\n        \"types\": [\"mocha\", \"webgl2\"]\n    },\n    \"include\": [\"../@types/**/*.d.ts\", \"src/**/*.ts\", \"test/**/*.ts\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "browser/tsconfig.test.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowUnreachableCode\": false,\n        \"allowUnusedLabels\": false,\n        \"experimentalDecorators\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"noEmitOnError\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"noImplicitAny\": true,\n        \"noImplicitReturns\": true,\n        \"noImplicitThis\": true,\n        \"noUnusedLocals\": true,\n        \"outDir\": \"../lib_test/browser\",\n        \"skipLibCheck\": true,\n        \"strictNullChecks\": false,\n        \"suppressImplicitAnyIndexErrors\": true,\n        \"target\": \"es2015\",\n        \"sourceMap\": true,\n        \"types\": [\"mocha\", \"webgl2\"]\n    },\n    \"include\": [\"../@types/**/*.d.ts\", \"src/**/*.ts\", \"src/**/*.tsx\", \"test/**/*.ts\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "browser/webpack.debug.config.js",
    "content": "const path = require(\"path\")\n\nconst webpack = require(\"webpack\")\n\n// Override 'development' settings\nconst baseConfig = require(\"./webpack.development.config.js\")\n\nconst debugConfig = Object.assign({}, baseConfig, {\n    devtool: \"source-map\",\n    plugins: [\n        new webpack.DefinePlugin({\n            \"process.env.NODE_ENV\": '\"development\"',\n        }),\n    ],\n    optimization: {\n        splitChunks: {\n            name: \"vendor\",\n            minChunks: 2,\n        },\n    },\n    output: {\n        path: path.join(__dirname, \"..\", \"lib\", \"browser\"),\n        publicPath: \"lib/browser/\",\n        filename: \"bundle.js\",\n        chunkFilename: \"[name].bundle.js\",\n    },\n})\n\nmodule.exports = debugConfig\n"
  },
  {
    "path": "browser/webpack.development.config.js",
    "content": "var path = require(\"path\")\nvar webpack = require(\"webpack\")\n\nconst createStyledComponentsTransformer = require(\"typescript-plugin-styled-components\").default\nconst styledComponentsTransformer = createStyledComponentsTransformer()\n\nmodule.exports = {\n    mode: \"development\",\n    entry: [path.join(__dirname, \"src/index.tsx\")],\n    target: \"electron-renderer\",\n    externals: {\n        \"vscode-jsonrpc\": \"require('vscode-jsonrpc')\",\n        \"vscode-textmate\": \"require('vscode-textmate')\",\n        \"vscode-languageserver-types\": \"require('vscode-languageserver-types')\",\n        \"keyboard-layout\": \"require('keyboard-layout')\",\n        gifshot: \"require('gifshot')\",\n        \"msgpack-lite\": \"require('msgpack-lite')\",\n        \"simple-git/promise\": \"require('simple-git/promise')\",\n        \"styled-components\": \"require('styled-components')\",\n        fsevents: \"require('fsevents')\",\n        \"font-manager\": \"require('font-manager')\",\n    },\n    resolve: {\n        extensions: [\".tsx\", \".ts\", \".js\", \".less\"],\n    },\n    module: {\n        rules: [\n            {\n                test: /\\.(html)$/,\n                use: {\n                    loader: \"html-loader\",\n                },\n            },\n            {\n                test: /\\.less$/,\n                use: [\n                    {\n                        loader: \"style-loader\", // creates style nodes from JS strings\n                    },\n                    {\n                        loader: \"css-loader\", // translates CSS into CommonJS\n                    },\n                    {\n                        loader: \"less-loader\", // compiles Less to CSS\n                    },\n                ],\n            },\n            {\n                test: /\\.css$/,\n                use: [\"style-loader\", \"css-loader\"],\n                exclude: /node_modules/,\n            },\n            {\n                test: /\\.tsx?$/,\n                use: {\n                    loader: \"ts-loader\",\n                    options: {\n                        getCustomTransformers: () => ({ before: [styledComponentsTransformer] }),\n                    },\n                },\n                exclude: /node_modules/,\n            },\n        ],\n    },\n    plugins: [\n        new webpack.DefinePlugin({\n            \"process.env.NODE_ENV\": '\"development\"',\n        }),\n    ],\n    output: {\n        path: path.join(__dirname, \"..\", \"lib\", \"browser\"),\n        publicPath: \"http://localhost:8191/\",\n        filename: \"bundle.js\",\n        chunkFilename: \"[name].bundle.js\",\n    },\n    node: {\n        process: false,\n        __dirname: false,\n    },\n}\n"
  },
  {
    "path": "browser/webpack.production.config.js",
    "content": "const path = require(\"path\")\n\nconst webpack = require(\"webpack\")\n\n// Override 'debug' settings\nconst baseConfig = require(\"./webpack.debug.config.js\")\n\nconst productionConfig = Object.assign({}, baseConfig, {\n    mode: \"production\",\n    devtool: false,\n    plugins: [\n        new webpack.DefinePlugin({\n            \"process.env.NODE_ENV\": '\"production\"',\n        }),\n    ],\n})\n\nmodule.exports = productionConfig\n"
  },
  {
    "path": "build/BuildSetupTemplate.js",
    "content": "// BuildSetupTemplate.js\n//\n// Helper script to insert template variables into the setup template\n\nconst path = require(\"path\")\nconst fs = require(\"fs\")\nconst os = require(\"os\")\n\nconst _ = require(\"lodash\")\nconst shelljs = require(\"shelljs\")\n\nconst sourceFile = path.join(__dirname, \"setup.template.iss\")\nconst destFile = path.join(__dirname, \"..\", \"dist\", \"setup.iss\")\n\nshelljs.rm(destFile)\n\nshelljs.cp(sourceFile, destFile)\n\nconst packageJsonContents = fs.readFileSync(path.join(__dirname, \"..\", \"package.json\"))\nconst packageMeta = JSON.parse(packageJsonContents)\nconst { version, name } = packageMeta\nconst prodName = packageMeta.build.productName\nconst pathVariable = \"{app}\\\\resources\\\\app\\\\cli\\\\win\\\\\"\n\nlet buildFolderPrefix = os.arch() === \"x32\" ? \"ia32-\" : \"\"\n\nif (process.env[\"APPVEYOR\"]) {\n    buildFolderPrefix = process.env[\"PLATFORM\"] === \"x86\" ? \"ia32-\" : \"\"\n}\n\n// Replace template variables\n\nconst valuesToReplace = {\n    AppName: prodName,\n    AppExecutableName: `${prodName}.exe`,\n    AppSetupExecutableName: `${prodName}-${version}-${buildFolderPrefix}win`,\n    Version: version,\n    SourcePath: path.join(__dirname, \"..\", \"dist\", `win-${buildFolderPrefix}unpacked`, \"*\"),\n    WizardImageFilePath: path.join(__dirname, \"setup\", \"Oni_128.bmp\"),\n    WizardSmallImageFilePath: path.join(__dirname, \"setup\", \"Oni_54.bmp\"),\n    cliPath: pathVariable,\n}\n\nconst addToEnv = `\nRoot: HKCU; Subkey: \"Environment\"; ValueType: expandsz; ValueName: \"Path\"; ValueData: \"{olddata};${pathVariable}\"; Tasks: addtopath; Check: NeedsAddPath(ExpandConstant('${pathVariable}'))\n\nRoot: HKCU; Subkey: \"SOFTWARE\\\\Classes\\\\*\\\\shell\\\\${prodName}\"; ValueType: expandsz; ValueName: \"\"; ValueData: \"Open with ${prodName}\"; Tasks: addToRightClickMenu; Flags: uninsdeletekey\nRoot: HKCU; Subkey: \"SOFTWARE\\\\Classes\\\\*\\\\shell\\\\${prodName}\"; ValueType: expandsz; ValueName: \"Icon\"; ValueData: \"{app}\\\\resources\\\\app\\\\images\\\\oni.ico\"; Tasks: addToRightClickMenu\nRoot: HKCU; Subkey: \"SOFTWARE\\\\Classes\\\\*\\\\shell\\\\${prodName}\\\\command\"; ValueType: expandsz; ValueName: \"\"; ValueData: \"\"\"{app}\\\\${prodName}.exe\"\" \"\"%1\"\"\"; Tasks: addToRightClickMenu\n`\n\nfunction getFileRegKey(ext, desc) {\n    return `\nRoot: HKCR; Subkey: \"${ext}\\\\OpenWithProgids\"; ValueType: none; ValueName: \"${prodName}\"; Flags: deletevalue uninsdeletevalue; Tasks: registerAsEditor;\nRoot: HKCR; Subkey: \"${ext}\\\\OpenWithProgids\"; ValueType: string; ValueName: \"${prodName}${ext}\"; ValueData: \"\"; Flags: uninsdeletevalue; Tasks: registerAsEditor;\nRoot: HKCR; Subkey: \"${prodName}${ext}\"; ValueType: string; ValueName: \"\"; ValueData: \"${desc}\"; Flags: uninsdeletekey; Tasks: registerAsEditor;\nRoot: HKCR; Subkey: \"${prodName}${ext}\\\\DefaultIcon\"; ValueType: string; ValueName: \"\"; ValueData: \"{app}\\\\resources\\\\app\\\\images\\\\oni.ico\"; Tasks: registerAsEditor;\nRoot: HKCR; Subkey: \"${prodName}${ext}\\\\shell\\\\open\\\\command\"; ValueType: string; ValueName: \"\"; ValueData: \"\"\"{app}\\\\${prodName}.exe\"\" \"\"%1\"\"\"; Tasks: registerAsEditor;\n`\n}\n\n_.keys(valuesToReplace).forEach(key => {\n    shelljs.sed(\"-i\", \"{{\" + key + \"}}\", valuesToReplace[key], destFile)\n})\n\nlet allFilesToAddRegKeysFor = \"\"\n\npackageMeta.build.fileAssociations.forEach(association => {\n    allFilesToAddRegKeysFor += getFileRegKey(`.${association.ext}`, association.name)\n})\n\nallFilesToAddRegKeysFor += addToEnv\n\nshelljs.sed(\"-i\", \"{{RegistryKey}}\", allFilesToAddRegKeysFor, destFile)\n"
  },
  {
    "path": "build/CopyIcons.js",
    "content": "// CopyIcons.js\n//\n// The windows packager requires an `icon.ico` and `installerIcon.ico`,\n// this script reuses the one we use for oni's menu bar.\n\nconst path = require(\"path\")\nconst fs = require(\"fs\")\n\nconst buf = fs.readFileSync(path.join(__dirname, \"..\", \"images\", \"oni.ico\"))\n\nfs.writeFileSync(path.join(__dirname, \"icon.ico\"), buf)\nfs.writeFileSync(path.join(__dirname, \"installerIcon.ico\"), buf)\n"
  },
  {
    "path": "build/script/CheckBinariesForBuild.js",
    "content": "/**\n * Helper script to validate the binaries we need for Oni.\n *\n * Because github throttles unauthenticated requests to download,\n * in some cases on the CI machines, we are unable to get the\n */\n\nconst path = require(\"path\")\nconst fs = require(\"fs\")\nconst mkdirp = require(\"mkdirp\")\nconst fsExtra = require(\"fs-extra\")\nconst os = require(\"os\")\n\nconst rootPath = path.join(__dirname, \"..\", \"..\")\nconst cachePath = path.join(rootPath, \".oni_build_cache\")\n\nconst modulesToCheck =\n    os.platform() !== \"linux\" ? [\"oni-neovim-binaries\", \"oni-ripgrep\"] : [\"oni-ripgrep\"]\n\nconst isAuthenticated = !!process.env[\"GITHUB_TOKEN\"]\n\nconst doBinFoldersExist = root => {\n    const fullPaths = modulesToCheck.map(m => path.join(root, \"node_modules\", m, \"bin\"))\n\n    let result = true\n\n    fullPaths.forEach(fp => {\n        console.log(\"- checking folder: \" + fp)\n        result = result && doesFolderExist(fp)\n    })\n\n    return result\n}\n\nconst copyFolders = (srcRoot, destRoot) => {\n    modulesToCheck.forEach(m => {\n        const srcDirectory = path.join(srcRoot, \"node_modules\", m)\n        const destDirectory = path.join(destRoot, \"node_modules\", m)\n        console.log(`- Copying from ${srcDirectory} to ${destDirectory}`)\n        fsExtra.copySync(srcDirectory, destDirectory)\n    })\n}\n\nconst doesFolderExist = folder => {\n    return fs.existsSync(folder) && fs.statSync(folder).isDirectory()\n}\n\nconsole.log(\"Checking binaries for build...\")\nconsole.log(\"- isAuthenticated: \" + isAuthenticated)\n\nconst foldersExist = doBinFoldersExist(rootPath)\nconst cacheFoldersExist = doBinFoldersExist(cachePath)\n\nconsole.log(\"- doBinFoldersExist in root: \" + foldersExist)\nconsole.log(\"- doBinFoldersExist in cache: \" + cacheFoldersExist)\n\nif (isAuthenticated && foldersExist) {\n    console.log(\"- Copying files to cache\")\n    copyFolders(rootPath, cachePath)\n    console.log(\"- Copy complete\")\n} else if (!isAuthenticated && !foldersExist && cacheFoldersExist) {\n    console.log(\"- Copying files from cache\")\n    copyFolders(cachePath, rootPath)\n    console.log(\"- Copy complete!\")\n}\n\n// Check again, now that files were copied if they needed to be copied\n\nconst finalCheckForBinaries = doBinFoldersExist(rootPath)\n\nconsole.log(\" - Final check for binaries in node_modules: \" + finalCheckForBinaries)\n\nif (!finalCheckForBinaries) {\n    console.log(\"Binary folders do not exist, cancelling build\")\n    process.exit(1)\n}\n"
  },
  {
    "path": "build/script/UploadDistributionBuildsToAzure.js",
    "content": "const azure = require(\"azure-storage\")\nconst util = require(\"util\")\nconst path = require(\"path\")\nconst fs = require(\"fs\")\nconst os = require(\"os\")\n\nconst AZURE_STORAGE_NAME = process.env[\"AZURE_STORAGE_NAME\"]\nconst AZURE_STORAGE_KEY = process.env[\"AZURE_STORAGE_KEY\"]\n\nconst COMMIT_ID = process.env[\"TRAVIS_COMMIT\"] || process.env[\"APPVEYOR_REPO_COMMIT\"]\n\nif (!COMMIT_ID || !AZURE_STORAGE_NAME || !AZURE_STORAGE_KEY) {\n    console.log(\"Skipping upload since this is a PR\")\n    process.exit(0)\n}\n\nconst blobService = azure.createBlobService(AZURE_STORAGE_NAME, AZURE_STORAGE_KEY)\n\nconst getBranch = () => process.env[\"APPVEYOR_REPO_BRANCH\"] || process.env[\"TRAVIS_BRANCH\"]\n\nconst branchName = getBranch()\n\nif (branchName !== \"master\") {\n    console.log(\"Skipping upload since this is not the master branch\")\n    process.exit(0)\n}\n\nconst getDistFolder = () => path.join(__dirname, \"..\", \"..\", \"dist\")\n\nconst getVersion = () => {\n    const packageJsonPath = path.join(getDistFolder(), \"..\", \"package.json\")\n    const packageInfo = JSON.parse(fs.readFileSync(packageJsonPath))\n    const version = packageInfo.version\n    return version\n}\n\nconst getBuildsForWindows = version => {\n    switch (process.env[\"PLATFORM\"]) {\n        case \"x86\":\n            return [`Oni-${version}-ia32-win.exe`, `Oni-${version}-ia32-win.zip`]\n        case \"x64\":\n            return [`Oni-${version}-win.exe`, `Oni-${version}-win.zip`]\n        default:\n            return []\n    }\n}\n\nconst getBuildsForPlatform = version => {\n    const platform = os.platform()\n\n    switch (platform) {\n        case \"win32\":\n            return getBuildsForWindows(version)\n        case \"darwin\":\n            return [`Oni-${version}-osx.dmg`]\n        case \"linux\":\n            return [\n                `Oni-${version}-amd64-linux.deb`,\n                `Oni-${version}-x86_64-linux.rpm`,\n                `Oni-${version}-x64-linux.tar.gz`,\n            ]\n        default:\n            return []\n    }\n}\n\nconst createContainerIfNotExists = containerName => {\n    return new Promise((resolve, reject) => {\n        blobService.createContainerIfNotExists(containerName, (err1, res1, response1) => {\n            if (err1) {\n                reject(err)\n                return\n            }\n\n            resolve(res1)\n        })\n    })\n}\n\nconst createBlockBlobFromFile = (containerName, blobName, filePath) => {\n    console.log(\n        `Uploading file - containerName: ${containerName} blobName: ${blobName} filePath: ${filePath}`,\n    )\n\n    return new Promise((resolve, reject) => {\n        blobService.createBlockBlobFromLocalFile(\n            containerName,\n            blobName,\n            filePath,\n            (err, result) => {\n                console.log(\"createBlockBlobFromLocalFile complete\")\n                if (err) {\n                    reject(err)\n                } else {\n                    resolve(result)\n                }\n            },\n        )\n    })\n}\n\nconst createBlockBlobFromText = (containerName, blobName, text) => {\n    console.log(`Uploading text - containerName: ${containerName} blobName: ${blobName}`)\n\n    return new Promise((resolve, reject) => {\n        blobService.createBlockBlobFromText(containerName, blobName, text, (err, result) => {\n            if (err) {\n                reject(err)\n            } else {\n                resolve(result)\n            }\n        })\n    })\n}\n\nconst getBlobsInContainer = containerName => {\n    return new Promise((resolve, reject) => {\n        blobService.listBlobsSegmented(containerName, null, (err, result) => {\n            if (err) {\n                reject(err)\n            } else {\n                resolve(result)\n            }\n        })\n    })\n}\n\nconst generateBuildMetadata = (branch, version) => {\n    return {\n        branch,\n        version,\n        commit: COMMIT_ID,\n        releaseNotesUrl: \"https://github.com/onivim/oni/wiki/Whats-New-in-Oni\",\n        releaseDate: new Date().getTime(),\n        containerName: getContainerName(branch, version, COMMIT_ID),\n    }\n}\n\nconst getContainerName = (branch, version, commit) => {\n    return branch + \"-\" + version.split(\".\").join(\"-\") + \"-\" + commit\n}\n\nconst start = async () => {\n    console.log(\"Creating download meta container...\")\n    await createContainerIfNotExists(\"downloadmeta\")\n\n    const containerName = getContainerName(getBranch(), getVersion(), COMMIT_ID)\n\n    console.log(\"Creating container for commit  \" + COMMIT_ID + \":\" + containerName)\n    await createContainerIfNotExists(containerName)\n\n    const version = getVersion()\n    console.log(\"Version: \" + version)\n\n    const builds = getBuildsForPlatform(version)\n\n    const distFolder = getDistFolder()\n    console.log(\"Dist folder: \" + distFolder)\n\n    const allPromises = builds.map(build => {\n        console.log(\"Uploading build: \" + build)\n        return createBlockBlobFromFile(containerName, build, path.join(distFolder, build))\n    })\n\n    await Promise.all(allPromises)\n\n    console.log(\"Reading blobs for commit...\")\n    const currentBlobs = await getBlobsInContainer(containerName)\n    const blobCount = currentBlobs.entries.length\n    console.log(\"Found \" + blobCount + \" uploaded.\")\n\n    if (blobCount === 8) {\n        console.log(\"All builds are uploaded. Creating metadata...\")\n        const metadata = generateBuildMetadata(getBranch(), getVersion())\n        console.dir(metadata)\n        const metadataAsString = JSON.stringify(metadata)\n        await createBlockBlobFromText(\"downloadmeta\", getBranch() + \".json\", metadataAsString)\n        console.log(\"Metadata uploaded!\")\n    } else {\n        console.log(\"Not all blobs have been uploaded; skipping metadata\")\n    }\n}\n\nstart()\n"
  },
  {
    "path": "build/script/appveyor-test.ps1",
    "content": "function exitIfFailed() {\n  if ($LastExitCode -ne 0) {\n    exit $LastExitCode\n  }\n}\n\n# Output useful info for debugging.\nnode --version\nnpm --version\n\nWrite-Host \"Platform: \" $env:PLATFORM\nWrite-Host \"AppVeyor: \" $env:APPVEYOR\n\n# Build\nyarn run build ; exitIfFailed\nyarn run lint ; exitIfFailed\nyarn run test:unit ; exitIfFailed\n\n# Create setup package\nyarn run copy-icons ; exitIfFailed\n\n$platform = (Get-Item env:PLATFORM).value\n\nif ($platform -eq \"x86\") {\n    yarn run dist:win:x86\n} else {\n    yarn run dist:win:x64\n}\n\nyarn run pack:win ; exitIfFailed\n\n# Run integration tests\nnpm run test:integration ; exitIfFailed\nnpm run test:setup ; exitIfFailed\n\n# Build up demo screenshot for commits that aren't PRs.\n$prNumber = (Get-Item env:APPVEYOR_PULL_REQUEST_NUMBER).value\n\nif ($prNumber -eq \"\") {\n    npm run demo:screenshot ; exitIfFailed\n}\n\n# Upload bits to azure\nnpm run upload:dist ; exitIfFailed\n"
  },
  {
    "path": "build/script/install-reason.sh",
    "content": "#!/usr/bin/env bash\n\nif [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then\n   echo Installing reason CLI tools...\n   npm install -g reason-cli@3.1.0-darwin\n   echo Reason CLI tools installed successfully.\n\n   echo NVIM_DIR: $NVIM_DIR\n   echo NODE_VERSION: $NODE_VERSION\n\n   echo Checking ocamlmerlin....\n   which ocamlmerlin\n   ocamlmerlin -version\n\n   PATH=$PATH:~/.nvm/versions/node/$NODE_VERSION/bin\nfi\n"
  },
  {
    "path": "build/script/travis-build.sh",
    "content": "#!/usr/bin/env bash\n\necho Travis build - detected OS is: \"$TRAVIS_OS_NAME\"\nset -e\n\nnode --version\nnpm --version\n\nnpm run build\nnpm run lint\n"
  },
  {
    "path": "build/script/travis-pack.sh",
    "content": "#!/usr/bin/env bash\n\necho Travis build - detected OS is: \"$TRAVIS_OS_NAME\"\nset -e\n\nif [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then\n    # Set debug flag for electron-builder, \n    # to troubleshoot intermittent failures with building the dmg\n    DEBUG=electron-builder,electron-builder:*\n    export DEBUG\nfi\n\nnpm run pack\n"
  },
  {
    "path": "build/script/travis-test.sh",
    "content": "#!/usr/bin/env bash\n\necho Travis build - detected OS is: \"$TRAVIS_OS_NAME\"\nset -e\n\nif [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then\n  # Initialize display driver\n  # This is needed for our unit tests (electron-mocha)\n  # and integration tests\n  DISPLAY=:99.0\n  export DISPLAY\n  sh -e /etc/init.d/xvfb start\n  sleep 3\n\n  # Install Neovim\n  curl -LO https://github.com/neovim/neovim/releases/download/v0.3.0/nvim.appimage\n  chmod u+x nvim.appimage\n  ./nvim.appimage --version\n  ONI_NEOVIM_PATH=\"$(cd \"$(dirname \"$1\")\"; pwd)/nvim.appimage\"\n  export ONI_NEOVIM_PATH\nfi\n\n\necho Using neovim path: \"$ONI_NEOVIM_PATH\"\n\nif [[ \"$TRAVIS_OS_NAME\" == \"osx\" && \"$TRAVIS_PULL_REQUEST\" == \"false\" ]]; then\n   npm run demo:screenshot\nfi\n\nnpm run test:unit\nnpm run test:integration\n\n# Upload master bits\nnpm run upload:dist\n\n# We'll run code coverage only on Linux, for now\nif [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then\n    npm run build:test:unit\n\n    ls -a lib_test/browser/src\n\n    npm run ccov:instrument\n\n    ls -a lib_test/browser/src_ccov\n\n    npm run ccov:upload:jest\n    npm run ccov:test:browser\n    npm run ccov:remap:browser:lcov\n    npm run ccov:clean\n    npm run ccov:upload\nfi\n"
  },
  {
    "path": "build/setup.template.iss",
    "content": "; setup.template.iss\n;\n; This is an InnoSetup script file used for generating the Windows Installer\n; Note that this is a template and variables of the form {{..}} should be replaced\n; by `BuildSetupTemplate.iss`. Variables of the form {..} are InnoSetup-specific variables.\n;\n; See http://www.jrsoftware.org/isinfo.php for more info\n\n\n[Setup]\nAppName={{AppName}}\nAppVersion={{Version}}\nDefaultDirName={pf}\\{{AppName}}\nDefaultGroupName={{AppName}}\nUninstallDisplayIcon={app}\\{{AppExecutableName}}\nCompression=zip\nSolidCompression=yes\nOutputBaseFilename={{AppSetupExecutableName}}\nWizardImageFile={{WizardImageFilePath}}\nWizardImageStretch=no\nWizardSmallImageFile={{WizardSmallImageFilePath}}\nChangesAssociations=yes\n\n[Files]\nSource: \"{{SourcePath}}\"; DestDir: \"{app}\"; Flags: ignoreversion recursesubdirs\n\n[Tasks]\nName: \"addtopath\"; Description: \"Add {{AppName}} to %PATH%\"; GroupDescription: \"Other\"\nName: \"registerAsEditor\"; Description: \"Register {{AppName}} as an editor for all supported file types.\"; GroupDescription: \"Other\"\nName: \"addToRightClickMenu\"; Description: \"Add {{AppName}} to the right click menu for all files.\"; GroupDescription: \"Other\"\n\n[Icons]\nName: \"{group}\\{{AppName}}\"; Filename: \"{app}\\{{AppExecutableName}}\"\n\n[Run]\nFilename: \"{app}\\{{AppName}}\"; Flags: postinstall skipifsilent nowait\n\n[Code]\nfunction NeedsAddPath(Param: string): boolean;\nvar\n  OrigPath: string;\nbegin\n  if not RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', OrigPath)\n  then begin\n    Result := True;\n    exit;\n  end;\n  Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;\nend;\n\n// http://stackoverflow.com/a/23838239/261019\nprocedure Explode(var Dest: TArrayOfString; Text: String; Separator: String);\nvar\n  i, p: Integer;\nbegin\n  i := 0;\n  repeat\n    SetArrayLength(Dest, i+1);\n    p := Pos(Separator,Text);\n    if p > 0 then begin\n      Dest[i] := Copy(Text, 1, p-1);\n      Text := Copy(Text, p + Length(Separator), Length(Text));\n      i := i + 1;\n    end else begin\n      Dest[i] := Text;\n      Text := '';\n    end;\n  until Length(Text)=0;\nend;\n\n// This update step checks for the old path variable ({app}) and removes it when installing if needed.\n// This is a modified version of the UninstallStepChanged, taken from VSCode.\nprocedure CurStepChanged(CurUninstallStep: TSetupStep);\nvar\n  Path: string;\n  OldOniPath: string;\n  Parts: TArrayOfString;\n  NewPath: string;\n  i: Integer;\nbegin\n  if not CurUninstallStep = ssInstall then begin\n    exit;\n  end;\n  if not RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', Path)\n  then begin\n    exit;\n  end;\n  NewPath := '';\n  OldOniPath := ExpandConstant('{app}')\n  Explode(Parts, Path, ';');\n  for i:=0 to GetArrayLength(Parts)-1 do begin\n    if CompareText(Parts[i], OldOniPath) <> 0 then begin\n      NewPath := NewPath + Parts[i];\n\n      if i < GetArrayLength(Parts) - 1 then begin\n        NewPath := NewPath + ';';\n      end;\n    end;\n  end;\n  RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', NewPath);\nend;\n\n// This is taken from the VSCode installer file.\nprocedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);\nvar\n  Path: string;\n  OniPath: string;\n  Parts: TArrayOfString;\n  NewPath: string;\n  i: Integer;\nbegin\n  if not CurUninstallStep = usUninstall then begin\n    exit;\n  end;\n  if not RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', Path)\n  then begin\n    exit;\n  end;\n  NewPath := '';\n  OniPath := ExpandConstant('{{cliPath}}')\n  Explode(Parts, Path, ';');\n  for i:=0 to GetArrayLength(Parts)-1 do begin\n    if CompareText(Parts[i], OniPath) <> 0 then begin\n      NewPath := NewPath + Parts[i];\n\n      if i < GetArrayLength(Parts) - 1 then begin\n        NewPath := NewPath + ';';\n      end;\n    end;\n  end;\n  RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', NewPath);\nend;\n\n[Registry]\n{{RegistryKey}}"
  },
  {
    "path": "cli/linux/oni.sh",
    "content": "#!/bin/bash\n\n# Get the path to the currently running script:\nself=$0\n\n# Test if $self is a symlink\nif [ -L \"$self\" ] ; then\n   # readlink returns the path to the file the link points to:\n   target=$(readlink \"$self\")\nelse\n   target=$self\nfi\n\nONI_PATH=$(dirname \"$target\")\nONI_EXECUTABLE=\"${ONI_PATH}/../../../../oni\"\nCLI_SCRIPT=\"${ONI_PATH}/../../lib/cli/src/cli.js\"\n\nELECTRON_RUN_AS_NODE=1 \"${ONI_EXECUTABLE}\" \"$CLI_SCRIPT\" \"$*\"\nexit $?"
  },
  {
    "path": "cli/mac/oni.sh",
    "content": "#!/bin/bash\n\n# Get the path to the currently running script:\nself=$0\n\n# Test if $self is a symlink\nif [ -L \"$self\" ] ; then\n   # readlink returns the path to the file the link points to:\n   target=$(readlink \"$self\")\nelse\n   target=$self\nfi\n\nONI_PATH=$(dirname \"$target\")\nONI_EXECUTABLE=\"${ONI_PATH}/../../../../MacOS/Oni\"\nCLI_SCRIPT=\"${ONI_PATH}/../../lib/cli/src/cli.js\"\n\nELECTRON_RUN_AS_NODE=1 \"${ONI_EXECUTABLE}\" \"$CLI_SCRIPT\" \"$*\"\nexit $?"
  },
  {
    "path": "cli/src/cli.ts",
    "content": "import * as path from \"path\"\nimport { CLIArgs, parseCLIProcessArgv } from \"./cli_args\"\n\nimport { spawn } from \"child_process\"\n\nexport async function main(cli_arguments: string[]): Promise<any> {\n    // First, try to parse the CLI args and deal with them.\n    let args: CLIArgs\n\n    try {\n        args = parseCLIProcessArgv(cli_arguments)\n    } catch (err) {\n        process.stdout.write(err.message)\n        throw err\n    }\n\n    if (args.help || args.version) {\n        const version = require(path.join(__dirname, \"..\", \"..\", \"..\", \"package.json\")).version // tslint:disable-line no-var-requires\n        process.stdout.write(\"Oni: Modern Modal Editing - powered by Neovim\\n\")\n        process.stdout.write(` version: ${version}\\n`)\n        process.stdout.write(\"\\nUsage:\\n oni [FILE]\\t\\tEdit file\\n\")\n        process.stdout.write(\"\\nhttps://github.com/onivim/oni\\n\")\n\n        return Promise.resolve(true)\n    }\n\n    // Otherwise, was loaded normally, so launch Oni.\n\n    const shellEnvPromise = import(\"shell-env\")\n    const shellEnv = (await shellEnvPromise).sync()\n\n    const env = assign({}, process.env, shellEnv, {\n        ONI_CLI: \"1\", // Let Oni know it was started from the CLI\n        ELECTRON_NO_ATTACH_CONSOLE: \"1\",\n    })\n\n    delete env[\"ELECTRON_RUN_AS_NODE\"]\n\n    const options = {\n        detached: true,\n        env,\n    }\n\n    const child = await spawn(process.execPath, cli_arguments.slice(2), options)\n    child.unref()\n\n    child.on(\"close\", code => {\n        if (code !== 0) {\n            throw Error(`Exit code was ${code}, not 0.`)\n        } else {\n            return Promise.resolve(true)\n        }\n    })\n\n    child.on(\"error\", err => {\n        throw err\n    })\n\n    child.on(\"exit\", code => {\n        if (code && code !== 0) {\n            throw Error(`Exit code was ${code}, not 0.`)\n        } else {\n            return Promise.resolve(true)\n        }\n    })\n}\n\nfunction assign(destination: any, ...sources: any[]): any {\n    sources.forEach(source => Object.keys(source).forEach(key => (destination[key] = source[key])))\n    return destination\n}\n\nfunction eventuallyExit(code: number): void {\n    setTimeout(() => process.exit(code), 0)\n}\n\nmain(process.argv)\n    .then(() => {\n        eventuallyExit(0)\n    })\n    .then(null, err => {\n        console.error(err.message || err.stack || err)\n        eventuallyExit(1)\n    })\n"
  },
  {
    "path": "cli/src/cli_args.ts",
    "content": "import * as minimist from \"minimist\"\n\nexport interface CLIArgs {\n    help?: boolean\n    version?: boolean\n    [arg: string]: any\n}\n\nconst options: minimist.Opts = {\n    boolean: [\"help\", \"version\"],\n    alias: {\n        help: \"h\",\n        version: \"v\",\n    },\n}\n\nexport function parseArgs(args: string[]): CLIArgs {\n    return minimist(args, options) as CLIArgs\n}\n\n// Skip the first 2 arguments as that is the location of the Electron binary,\n// and the location of the cli.ts script.\nexport function parseCLIProcessArgv(processArgv: string[]): CLIArgs {\n    let [, , ...args] = processArgv\n\n    return parseArgs(args)\n}\n"
  },
  {
    "path": "cli/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowUnreachableCode\": false,\n        \"allowUnusedLabels\": false,\n        \"experimentalDecorators\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"newLine\": \"LF\",\n        \"noEmitOnError\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"noImplicitReturns\": true,\n        \"noImplicitThis\": true,\n        \"noUnusedLocals\": true,\n        \"outDir\": \"../lib/cli\",\n        \"pretty\": true,\n        \"removeComments\": true,\n        \"rootDir\": \".\",\n        \"skipLibCheck\": true,\n        \"strictNullChecks\": false,\n        \"suppressImplicitAnyIndexErrors\": true,\n        \"target\": \"es2015\",\n        \"sourceMap\": true\n    },\n    \"include\": [\"src/**/*.ts\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "cli/win/oni.cmd",
    "content": "@echo off\nsetlocal\nset ELECTRON_RUN_AS_NODE=1\ncall \"%~dp0..\\..\\..\\..\\Oni.exe\" \"%~dp0..\\..\\lib\\cli\\src\\cli.js\" %*\nendlocal"
  },
  {
    "path": "codecov.yml",
    "content": "ignore:\n    - \"dist/.*\"\n\n"
  },
  {
    "path": "configuration/config.default.js",
    "content": "// For more information on customizing Oni,\n// check out our wiki page:\n// https://github.com/onivim/oni/wiki/Configuration\n\nconst activate = oni => {\n    console.log(\"config activated\")\n\n    // Input\n    //\n    // Add input bindings here:\n    //\n    oni.input.bind(\"<f11>\", \"oni.debug.openDevTools\")\n    oni.input.bind(\"<c-enter>\", () => console.log(\"Control+Enter was pressed\"))\n\n    //\n    // Or remove the default bindings:\n    //\n    // oni.input.unbind(\"<c-p>\")\n}\n\nconst deactivate = () => {\n    console.log(\"config deactivated\")\n}\n\nmodule.exports = {\n    activate,\n    deactivate,\n    //add custom config here, such as\n\n    \"ui.colorscheme\": \"nord\",\n\n    //\"oni.useDefaultConfig\": true,\n    //\"oni.bookmarks\": [\"~/Documents\"],\n    //\"oni.loadInitVim\": false,\n    //\"editor.fontSize\": \"14px\",\n    //\"editor.fontFamily\": \"Monaco\",\n\n    // UI customizations\n    \"ui.animations.enabled\": true,\n    \"ui.fontSmoothing\": \"auto\",\n}\n"
  },
  {
    "path": "extensions/README.md",
    "content": "# NOTE TO CONTRIBUTORS\n\n- The majority of these syntaxes (and configurations) are brought from the VSCode repository: https://github.com/Microsoft/vscode\n\nExceptions:\n- reason - brought from the `vscode-reasonml` repository: https://github.com/reasonml-editor/vscode-reasonml\n"
  },
  {
    "path": "extensions/clojure/syntaxes/clojure.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-clojure/blob/master/grammars/clojure.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-clojure/commit/ecc790326bc8e14220e4d2d72a392a30876c3219\",\n    \"name\": \"Clojure\",\n    \"scopeName\": \"source.clojure\",\n    \"patterns\": [\n        {\n            \"include\": \"#comment\"\n        },\n        {\n            \"include\": \"#shebang-comment\"\n        },\n        {\n            \"include\": \"#quoted-sexp\"\n        },\n        {\n            \"include\": \"#sexp\"\n        },\n        {\n            \"include\": \"#keyfn\"\n        },\n        {\n            \"include\": \"#string\"\n        },\n        {\n            \"include\": \"#vector\"\n        },\n        {\n            \"include\": \"#set\"\n        },\n        {\n            \"include\": \"#map\"\n        },\n        {\n            \"include\": \"#regexp\"\n        },\n        {\n            \"include\": \"#var\"\n        },\n        {\n            \"include\": \"#constants\"\n        },\n        {\n            \"include\": \"#dynamic-variables\"\n        },\n        {\n            \"include\": \"#metadata\"\n        },\n        {\n            \"include\": \"#namespace-symbol\"\n        },\n        {\n            \"include\": \"#symbol\"\n        }\n    ],\n    \"repository\": {\n        \"comment\": {\n            \"begin\": \"(?<!\\\\\\\\);\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.clojure\"\n                }\n            },\n            \"end\": \"$\",\n            \"name\": \"comment.line.semicolon.clojure\"\n        },\n        \"constants\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(nil)(?=(\\\\s|\\\\)|\\\\]|\\\\}))\",\n                    \"name\": \"constant.language.nil.clojure\"\n                },\n                {\n                    \"match\": \"(true|false)\",\n                    \"name\": \"constant.language.boolean.clojure\"\n                },\n                {\n                    \"match\": \"(-?\\\\d+/\\\\d+)\",\n                    \"name\": \"constant.numeric.ratio.clojure\"\n                },\n                {\n                    \"match\": \"(-?\\\\d+[rR][0-9a-zA-Z]+)\",\n                    \"name\": \"constant.numeric.arbitrary-radix.clojure\"\n                },\n                {\n                    \"match\": \"(-?0[xX][0-9a-fA-F]+)\",\n                    \"name\": \"constant.numeric.hexadecimal.clojure\"\n                },\n                {\n                    \"match\": \"(-?0\\\\d+)\",\n                    \"name\": \"constant.numeric.octal.clojure\"\n                },\n                {\n                    \"match\": \"(-?\\\\d+\\\\.\\\\d+([eE][+-]?\\\\d+)?M)\",\n                    \"name\": \"constant.numeric.bigdecimal.clojure\"\n                },\n                {\n                    \"match\": \"(-?\\\\d+\\\\.\\\\d+([eE][+-]?\\\\d+)?)\",\n                    \"name\": \"constant.numeric.double.clojure\"\n                },\n                {\n                    \"match\": \"(-?\\\\d+N)\",\n                    \"name\": \"constant.numeric.bigint.clojure\"\n                },\n                {\n                    \"match\": \"(-?\\\\d+)\",\n                    \"name\": \"constant.numeric.long.clojure\"\n                },\n                {\n                    \"include\": \"#keyword\"\n                }\n            ]\n        },\n        \"keyword\": {\n            \"match\":\n                \"(?<=(\\\\s|\\\\(|\\\\[|\\\\{)):[a-zA-Z0-9\\\\#\\\\.\\\\-\\\\_\\\\:\\\\+\\\\=\\\\>\\\\<\\\\/\\\\!\\\\?\\\\*]+(?=(\\\\s|\\\\)|\\\\]|\\\\}|\\\\,))\",\n            \"name\": \"constant.keyword.clojure\"\n        },\n        \"keyfn\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<=(\\\\s|\\\\(|\\\\[|\\\\{))(if(-[-a-z\\\\?]*)?|when(-[-a-z]*)?|for(-[-a-z]*)?|cond|do|let(-[-a-z\\\\?]*)?|binding|loop|recur|fn|throw[a-z\\\\-]*|try|catch|finally|([a-z]*case))(?=(\\\\s|\\\\)|\\\\]|\\\\}))\",\n                    \"name\": \"storage.control.clojure\"\n                },\n                {\n                    \"match\":\n                        \"(?<=(\\\\s|\\\\(|\\\\[|\\\\{))(declare-?|(in-)?ns|import|use|require|load|compile|(def[a-z\\\\-]*))(?=(\\\\s|\\\\)|\\\\]|\\\\}))\",\n                    \"name\": \"keyword.control.clojure\"\n                }\n            ]\n        },\n        \"dynamic-variables\": {\n            \"match\": \"\\\\*[\\\\w\\\\.\\\\-\\\\_\\\\:\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\d]+\\\\*\",\n            \"name\": \"meta.symbol.dynamic.clojure\"\n        },\n        \"map\": {\n            \"begin\": \"(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.map.begin.clojure\"\n                }\n            },\n            \"end\": \"(\\\\}(?=[\\\\}\\\\]\\\\)\\\\s]*(?:;|$)))|(\\\\})\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.map.end.trailing.clojure\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.map.end.clojure\"\n                }\n            },\n            \"name\": \"meta.map.clojure\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"metadata\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(\\\\^\\\\{)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.metadata.map.begin.clojure\"\n                        }\n                    },\n                    \"end\": \"(\\\\}(?=[\\\\}\\\\]\\\\)\\\\s]*(?:;|$)))|(\\\\})\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.metadata.map.end.trailing.clojure\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.metadata.map.end.clojure\"\n                        }\n                    },\n                    \"name\": \"meta.metadata.map.clojure\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(\\\\^)\",\n                    \"end\": \"(\\\\s)\",\n                    \"name\": \"meta.metadata.simple.clojure\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#keyword\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"quoted-sexp\": {\n            \"begin\": \"(['``]\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.expression.begin.clojure\"\n                }\n            },\n            \"end\": \"(\\\\))$|(\\\\)(?=[\\\\}\\\\]\\\\)\\\\s]*(?:;|$)))|(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.expression.end.trailing.clojure\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.expression.end.trailing.clojure\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.section.expression.end.clojure\"\n                }\n            },\n            \"name\": \"meta.quoted-expression.clojure\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"regexp\": {\n            \"begin\": \"#\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.regexp.begin.clojure\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.regexp.end.clojure\"\n                }\n            },\n            \"name\": \"string.regexp.clojure\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp_escaped_char\"\n                }\n            ]\n        },\n        \"regexp_escaped_char\": {\n            \"match\": \"\\\\\\\\.\",\n            \"name\": \"constant.character.escape.clojure\"\n        },\n        \"set\": {\n            \"begin\": \"(\\\\#\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.set.begin.clojure\"\n                }\n            },\n            \"end\": \"(\\\\}(?=[\\\\}\\\\]\\\\)\\\\s]*(?:;|$)))|(\\\\})\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.set.end.trailing.clojure\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.set.end.clojure\"\n                }\n            },\n            \"name\": \"meta.set.clojure\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"sexp\": {\n            \"begin\": \"(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.expression.begin.clojure\"\n                }\n            },\n            \"end\": \"(\\\\))$|(\\\\)(?=[\\\\}\\\\]\\\\)\\\\s]*(?:;|$)))|(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.expression.end.trailing.clojure\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.expression.end.trailing.clojure\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.section.expression.end.clojure\"\n                }\n            },\n            \"name\": \"meta.expression.clojure\",\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?<=\\\\()(ns|declare|def[\\\\w\\\\d._:+=><!?*-]*|[\\\\w._:+=><!?*-][\\\\w\\\\d._:+=><!?*-]*/def[\\\\w\\\\d._:+=><!?*-]*)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.clojure\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\))\",\n                    \"name\": \"meta.definition.global.clojure\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#metadata\"\n                        },\n                        {\n                            \"include\": \"#dynamic-variables\"\n                        },\n                        {\n                            \"match\":\n                                \"([a-zA-Z\\\\.\\\\-\\\\_\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\*][\\\\w\\\\.\\\\-\\\\_\\\\:\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\*\\\\d]*)\",\n                            \"name\": \"entity.global.clojure\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#keyfn\"\n                },\n                {\n                    \"include\": \"#constants\"\n                },\n                {\n                    \"include\": \"#vector\"\n                },\n                {\n                    \"include\": \"#map\"\n                },\n                {\n                    \"include\": \"#set\"\n                },\n                {\n                    \"include\": \"#sexp\"\n                },\n                {\n                    \"match\": \"(?<=\\\\()(.+?)(?=\\\\s|\\\\))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.clojure\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"shebang-comment\": {\n            \"begin\": \"^(#!)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.shebang.clojure\"\n                }\n            },\n            \"end\": \"$\",\n            \"name\": \"comment.line.shebang.clojure\"\n        },\n        \"string\": {\n            \"begin\": \"(?<!\\\\\\\\)(\\\")\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.begin.clojure\"\n                }\n            },\n            \"end\": \"(\\\")\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.clojure\"\n                }\n            },\n            \"name\": \"string.quoted.double.clojure\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\.\",\n                    \"name\": \"constant.character.escape.clojure\"\n                }\n            ]\n        },\n        \"namespace-symbol\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"([a-zA-Z\\\\.\\\\-\\\\_\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\*][\\\\w\\\\.\\\\-\\\\_\\\\:\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\*\\\\d]*)/\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"meta.symbol.namespace.clojure\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"symbol\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"([a-zA-Z\\\\.\\\\-\\\\_\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\*][\\\\w\\\\.\\\\-\\\\_\\\\:\\\\+\\\\=\\\\>\\\\<\\\\!\\\\?\\\\*\\\\d]*)\",\n                    \"name\": \"meta.symbol.clojure\"\n                }\n            ]\n        },\n        \"var\": {\n            \"match\":\n                \"(?<=(\\\\s|\\\\(|\\\\[|\\\\{)\\\\#)'[a-zA-Z0-9\\\\.\\\\-\\\\_\\\\:\\\\+\\\\=\\\\>\\\\<\\\\/\\\\!\\\\?\\\\*]+(?=(\\\\s|\\\\)|\\\\]|\\\\}))\",\n            \"name\": \"meta.var.clojure\"\n        },\n        \"vector\": {\n            \"begin\": \"(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.vector.begin.clojure\"\n                }\n            },\n            \"end\": \"(\\\\](?=[\\\\}\\\\]\\\\)\\\\s]*(?:;|$)))|(\\\\])\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.vector.end.trailing.clojure\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.vector.end.clojure\"\n                }\n            },\n            \"name\": \"meta.vector.clojure\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/csharp/syntaxes/csharp.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/dotnet/csharp-tmLanguage/blob/master/grammars/csharp.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/dotnet/csharp-tmLanguage/commit/2904dae001939996c6a3484eac1b95716797ac41\",\n    \"name\": \"C#\",\n    \"scopeName\": \"source.cs\",\n    \"patterns\": [\n        {\n            \"include\": \"#preprocessor\"\n        },\n        {\n            \"include\": \"#comment\"\n        },\n        {\n            \"include\": \"#directives\"\n        },\n        {\n            \"include\": \"#declarations\"\n        },\n        {\n            \"include\": \"#script-top-level\"\n        }\n    ],\n    \"repository\": {\n        \"directives\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#extern-alias-directive\"\n                },\n                {\n                    \"include\": \"#using-directive\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"declarations\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#namespace-declaration\"\n                },\n                {\n                    \"include\": \"#type-declarations\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"script-top-level\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#statement\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"type-declarations\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#storage-modifier\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#delegate-declaration\"\n                },\n                {\n                    \"include\": \"#enum-declaration\"\n                },\n                {\n                    \"include\": \"#interface-declaration\"\n                },\n                {\n                    \"include\": \"#struct-declaration\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"class-or-struct-members\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#storage-modifier\"\n                },\n                {\n                    \"include\": \"#type-declarations\"\n                },\n                {\n                    \"include\": \"#property-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#event-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#constructor-declaration\"\n                },\n                {\n                    \"include\": \"#destructor-declaration\"\n                },\n                {\n                    \"include\": \"#operator-declaration\"\n                },\n                {\n                    \"include\": \"#conversion-operator-declaration\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"interface-members\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#property-declaration\"\n                },\n                {\n                    \"include\": \"#event-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#while-statement\"\n                },\n                {\n                    \"include\": \"#do-statement\"\n                },\n                {\n                    \"include\": \"#for-statement\"\n                },\n                {\n                    \"include\": \"#foreach-statement\"\n                },\n                {\n                    \"include\": \"#if-statement\"\n                },\n                {\n                    \"include\": \"#else-part\"\n                },\n                {\n                    \"include\": \"#switch-statement\"\n                },\n                {\n                    \"include\": \"#goto-statement\"\n                },\n                {\n                    \"include\": \"#return-statement\"\n                },\n                {\n                    \"include\": \"#break-or-continue-statement\"\n                },\n                {\n                    \"include\": \"#throw-statement\"\n                },\n                {\n                    \"include\": \"#yield-statement\"\n                },\n                {\n                    \"include\": \"#await-statement\"\n                },\n                {\n                    \"include\": \"#try-statement\"\n                },\n                {\n                    \"include\": \"#checked-unchecked-statement\"\n                },\n                {\n                    \"include\": \"#lock-statement\"\n                },\n                {\n                    \"include\": \"#using-statement\"\n                },\n                {\n                    \"include\": \"#labeled-statement\"\n                },\n                {\n                    \"include\": \"#local-declaration\"\n                },\n                {\n                    \"include\": \"#block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#checked-unchecked-expression\"\n                },\n                {\n                    \"include\": \"#typeof-or-default-expression\"\n                },\n                {\n                    \"include\": \"#nameof-expression\"\n                },\n                {\n                    \"include\": \"#throw-expression\"\n                },\n                {\n                    \"include\": \"#interpolated-string\"\n                },\n                {\n                    \"include\": \"#verbatim-interpolated-string\"\n                },\n                {\n                    \"include\": \"#this-or-base-expression\"\n                },\n                {\n                    \"include\": \"#conditional-operator\"\n                },\n                {\n                    \"include\": \"#expression-operators\"\n                },\n                {\n                    \"include\": \"#await-expression\"\n                },\n                {\n                    \"include\": \"#query-expression\"\n                },\n                {\n                    \"include\": \"#as-expression\"\n                },\n                {\n                    \"include\": \"#is-expression\"\n                },\n                {\n                    \"include\": \"#anonymous-method-expression\"\n                },\n                {\n                    \"include\": \"#object-creation-expression\"\n                },\n                {\n                    \"include\": \"#array-creation-expression\"\n                },\n                {\n                    \"include\": \"#anonymous-object-creation-expression\"\n                },\n                {\n                    \"include\": \"#invocation-expression\"\n                },\n                {\n                    \"include\": \"#member-access-expression\"\n                },\n                {\n                    \"include\": \"#element-access-expression\"\n                },\n                {\n                    \"include\": \"#cast-expression\"\n                },\n                {\n                    \"include\": \"#literal\"\n                },\n                {\n                    \"include\": \"#parenthesized-expression\"\n                },\n                {\n                    \"include\": \"#tuple-deconstruction-assignment\"\n                },\n                {\n                    \"include\": \"#initializer-expression\"\n                },\n                {\n                    \"include\": \"#identifier\"\n                }\n            ]\n        },\n        \"extern-alias-directive\": {\n            \"begin\": \"\\\\s*(extern)\\\\b\\\\s*(alias)\\\\b\\\\s*(@?[_[:alpha:]][_[:alnum:]]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.extern.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.alias.cs\"\n                },\n                \"3\": {\n                    \"name\": \"variable.other.alias.cs\"\n                }\n            },\n            \"end\": \"(?=;)\"\n        },\n        \"using-directive\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(using)\\\\b\\\\s+(static)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.using.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.static.cs\"\n                        }\n                    },\n                    \"end\": \"(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b(using)\\\\s+(?=(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*=)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.using.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.type.alias.cs\"\n                        }\n                    },\n                    \"end\": \"(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#operator-assignment\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b(using)\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.using.cs\"\n                        }\n                    },\n                    \"end\": \"(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"name\": \"entity.name.type.namespace.cs\",\n                            \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                        },\n                        {\n                            \"include\": \"#operator-assignment\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"attribute-section\": {\n            \"begin\": \"(\\\\[)(assembly|module|field|event|method|param|property|return|type)?(\\\\:)?\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.squarebracket.open.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.attribute-specifier.cs\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                }\n            },\n            \"end\": \"(\\\\])\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.squarebracket.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#attribute\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"attribute\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#type-name\"\n                },\n                {\n                    \"include\": \"#attribute-arguments\"\n                }\n            ]\n        },\n        \"attribute-arguments\": {\n            \"begin\": \"(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#attribute-named-argument\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"attribute-named-argument\": {\n            \"begin\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(?==)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.variable.property.cs\"\n                }\n            },\n            \"end\": \"(?=(,|\\\\)))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#operator-assignment\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"namespace-declaration\": {\n            \"begin\": \"\\\\b(namespace)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.namespace.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"entity.name.type.namespace.cs\",\n                    \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#declarations\"\n                        },\n                        {\n                            \"include\": \"#using-directive\"\n                        },\n                        {\n                            \"include\": \"#punctuation-semicolon\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"storage-modifier\": {\n            \"name\": \"storage.modifier.cs\",\n            \"match\":\n                \"(?<!\\\\.)\\\\b(new|public|protected|internal|private|abstract|virtual|override|sealed|static|partial|readonly|volatile|const|extern|async|unsafe|ref)\\\\b\"\n        },\n        \"class-declaration\": {\n            \"begin\": \"(?=\\\\bclass\\\\b)\",\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?x)\\n\\\\b(class)\\\\b\\\\s+\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.class.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.type.class.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\{)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameter-list\"\n                        },\n                        {\n                            \"include\": \"#base-types\"\n                        },\n                        {\n                            \"include\": \"#generic-constraints\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#class-or-struct-members\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"delegate-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?:\\\\b(delegate)\\\\b)\\\\s+\\n(?<type-name>\\n  (?:\\n    (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref return\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\s*\\n(<([^<>]+)>)?\\\\s*\\n(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.delegate.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.type.delegate.cs\"\n                },\n                \"8\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-parameter-list\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parenthesized-parameter-list\"\n                },\n                {\n                    \"include\": \"#generic-constraints\"\n                }\n            ]\n        },\n        \"enum-declaration\": {\n            \"begin\": \"(?=\\\\benum\\\\b)\",\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?=enum)\",\n                    \"end\": \"(?=\\\\{)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"match\": \"(enum)\\\\s+(@?[_[:alpha:]][_[:alnum:]]*)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.enum.cs\"\n                                },\n                                \"2\": {\n                                    \"name\": \"entity.name.type.enum.cs\"\n                                }\n                            }\n                        },\n                        {\n                            \"begin\": \":\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.separator.colon.cs\"\n                                }\n                            },\n                            \"end\": \"(?=\\\\{)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#type\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#preprocessor\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#attribute-section\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        },\n                        {\n                            \"begin\": \"@?[_[:alpha:]][_[:alnum:]]*\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.variable.enum-member.cs\"\n                                }\n                            },\n                            \"end\": \"(?=(,|\\\\}))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"interface-declaration\": {\n            \"begin\": \"(?=\\\\binterface\\\\b)\",\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?x)\\n(interface)\\\\b\\\\s+\\n(@?[_[:alpha:]][_[:alnum:]]*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.interface.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.type.interface.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\{)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameter-list\"\n                        },\n                        {\n                            \"include\": \"#base-types\"\n                        },\n                        {\n                            \"include\": \"#generic-constraints\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interface-members\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"struct-declaration\": {\n            \"begin\": \"(?=\\\\bstruct\\\\b)\",\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?x)\\n(struct)\\\\b\\\\s+\\n(@?[_[:alpha:]][_[:alnum:]]*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.struct.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.type.struct.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\{)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameter-list\"\n                        },\n                        {\n                            \"include\": \"#base-types\"\n                        },\n                        {\n                            \"include\": \"#generic-constraints\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#class-or-struct-members\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"type-parameter-list\": {\n            \"begin\": \"\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.typeparameters.begin.cs\"\n                }\n            },\n            \"end\": \"\\\\>\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.typeparameters.end.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(in|out)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.type-parameter.cs\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                }\n            ]\n        },\n        \"base-types\": {\n            \"begin\": \":\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                }\n            },\n            \"end\": \"(?=\\\\{|where)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#preprocessor\"\n                }\n            ]\n        },\n        \"generic-constraints\": {\n            \"begin\": \"(where)\\\\s+(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.where.cs\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.cs\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                }\n            },\n            \"end\": \"(?=\\\\{|where|;|=>)\",\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.other.class.cs\",\n                    \"match\": \"\\\\bclass\\\\b\"\n                },\n                {\n                    \"name\": \"keyword.other.struct.cs\",\n                    \"match\": \"\\\\bstruct\\\\b\"\n                },\n                {\n                    \"match\": \"(new)\\\\s*(\\\\()\\\\s*(\\\\))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.new.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#generic-constraints\"\n                }\n            ]\n        },\n        \"field-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\s* # first field name\\n(?!=>|==)(?=,|;|=|$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"6\": {\n                    \"name\": \"entity.name.variable.field.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"name\": \"entity.name.variable.field.cs\",\n                    \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#class-or-struct-members\"\n                }\n            ]\n        },\n        \"property-declaration\": {\n            \"begin\":\n                \"(?x)\\n\\n# The negative lookahead below ensures that we don't match nested types\\n# or other declarations as properties.\\n(?![[:word:][:space:]]*\\\\b(?:class|interface|struct|enum|event)\\\\b)\\n\\n(?<return-type>\\n  (?<type-name>\\n    (?:\\n      (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref return\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\\\s+\\n)\\n(?<interface-name>\\\\g<type-name>\\\\s*\\\\.\\\\s*)?\\n(?<property-name>\\\\g<identifier>)\\\\s*\\n(?=\\\\{|=>|$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        }\n                    ]\n                },\n                \"8\": {\n                    \"name\": \"entity.name.variable.property.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#property-accessors\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#class-or-struct-members\"\n                }\n            ]\n        },\n        \"indexer-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?<return-type>\\n  (?<type-name>\\n    (?:\\n      (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref return\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\\\s+\\n)\\n(?<interface-name>\\\\g<type-name>\\\\s*\\\\.\\\\s*)?\\n(?<indexer-name>this)\\\\s*\\n(?=\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        }\n                    ]\n                },\n                \"8\": {\n                    \"name\": \"keyword.other.this.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#bracketed-parameter-list\"\n                },\n                {\n                    \"include\": \"#property-accessors\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"event-declaration\": {\n            \"begin\":\n                \"(?x)\\n\\\\b(event)\\\\b\\\\s*\\n(?<return-type>\\n  (?<type-name>\\n    (?:\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\\\s+\\n)\\n(?<interface-name>\\\\g<type-name>\\\\s*\\\\.\\\\s*)?\\n(?<event-names>\\\\g<identifier>(?:\\\\s*,\\\\s*\\\\g<identifier>)*)\\\\s*\\n(?=\\\\{|;|$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.event.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"8\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        }\n                    ]\n                },\n                \"9\": {\n                    \"patterns\": [\n                        {\n                            \"name\": \"entity.name.variable.event.cs\",\n                            \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#event-accessors\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"property-accessors\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.open.cs\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"storage.modifier.cs\",\n                    \"match\": \"\\\\b(private|protected|internal)\\\\b\"\n                },\n                {\n                    \"name\": \"keyword.other.get.cs\",\n                    \"match\": \"\\\\b(get)\\\\b\"\n                },\n                {\n                    \"name\": \"keyword.other.set.cs\",\n                    \"match\": \"\\\\b(set)\\\\b\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"event-accessors\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.open.cs\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.other.add.cs\",\n                    \"match\": \"\\\\b(add)\\\\b\"\n                },\n                {\n                    \"name\": \"keyword.other.remove.cs\",\n                    \"match\": \"\\\\b(remove)\\\\b\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"method-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?<return-type>\\n  (?<type-name>\\n    (?:\\n      (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref return\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\\\s+\\n)\\n(?<interface-name>\\\\g<type-name>\\\\s*\\\\.\\\\s*)?\\n(\\\\g<identifier>)\\\\s*\\n(<([^<>]+)>)?\\\\s*\\n(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        }\n                    ]\n                },\n                \"8\": {\n                    \"name\": \"entity.name.function.cs\"\n                },\n                \"9\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-parameter-list\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parenthesized-parameter-list\"\n                },\n                {\n                    \"include\": \"#generic-constraints\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"constructor-declaration\": {\n            \"begin\": \"(?=@?[_[:alpha:]][_[:alnum:]]*\\\\s*\\\\()\",\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"match\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.cs\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.colon.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\{|=>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#constructor-initializer\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#parenthesized-parameter-list\"\n                },\n                {\n                    \"include\": \"#preprocessor\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"constructor-initializer\": {\n            \"begin\": \"\\\\b(?:(base)|(this))\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.base.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.this.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#argument-list\"\n                }\n            ]\n        },\n        \"destructor-declaration\": {\n            \"begin\": \"(~)(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.tilde.cs\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parenthesized-parameter-list\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"operator-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?<type-name>\\n  (?:\\n    (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref return\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s*\\n(?<operator-keyword>(?:\\\\b(?:operator)))\\\\s*\\n(?<operator>(?:\\\\+|-|\\\\*|/|%|&|\\\\||\\\\^|\\\\<\\\\<|\\\\>\\\\>|==|!=|\\\\>|\\\\<|\\\\>=|\\\\<=|!|~|\\\\+\\\\+|--|true|false))\\\\s*\\n(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"6\": {\n                    \"name\": \"keyword.other.operator-decl.cs\"\n                },\n                \"7\": {\n                    \"name\": \"entity.name.function.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parenthesized-parameter-list\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"conversion-operator-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?<explicit-or-implicit-keyword>(?:\\\\b(?:explicit|implicit)))\\\\s*\\n(?<operator-keyword>(?:\\\\b(?:operator)))\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref return\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s*\\n(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\b(explicit)\\\\b\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.explicit.cs\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"\\\\b(implicit)\\\\b\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.implicit.cs\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.operator-decl.cs\"\n                },\n                \"3\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parenthesized-parameter-list\"\n                },\n                {\n                    \"include\": \"#expression-body\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"block\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.open.cs\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"variable-initializer\": {\n            \"begin\": \"(?<!=|!)(=)(?!=|>)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.assignment.cs\"\n                }\n            },\n            \"end\": \"(?=[,\\\\)\\\\];}])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#ref-modifier\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"expression-body\": {\n            \"begin\": \"=>\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.arrow.cs\"\n                }\n            },\n            \"end\": \"(?=[,\\\\);}])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#ref-modifier\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"goto-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(goto)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.goto.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(case)\\\\b\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.case.cs\"\n                        }\n                    },\n                    \"end\": \"(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"\\\\b(default)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.default.cs\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.label.cs\",\n                    \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                }\n            ]\n        },\n        \"return-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(return)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.return.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#ref-modifier\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"break-or-continue-statement\": {\n            \"match\": \"(?<!\\\\.)\\\\b(?:(break)|(continue))\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.break.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.flow.continue.cs\"\n                }\n            }\n        },\n        \"throw-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(throw)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.throw.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"yield-statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#yield-return-statement\"\n                },\n                {\n                    \"include\": \"#yield-break-statement\"\n                }\n            ]\n        },\n        \"yield-return-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(yield)\\\\b\\\\s*\\\\b(return)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.yield.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.flow.return.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"yield-break-statement\": {\n            \"match\": \"(?<!\\\\.)\\\\b(yield)\\\\b\\\\s*\\\\b(break)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.yield.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.flow.break.cs\"\n                }\n            }\n        },\n        \"await-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(await)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.await.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"if-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(if)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.conditional.if.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"else-part\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(else)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.conditional.else.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"switch-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(switch)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.switch.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.curlybrace.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#switch-label\"\n                        },\n                        {\n                            \"include\": \"#statement\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"switch-label\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<!\\\\.)\\\\b(case)\\\\b\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.case.cs\"\n                        }\n                    },\n                    \"end\": \":\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.separator.colon.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(?<!\\\\.)\\\\b(default)\\\\b\\\\s*(:)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.default.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.colon.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"do-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(do)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.do.cs\"\n                }\n            },\n            \"end\": \"(?=;|})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"while-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(while)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.while.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"for-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(for)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.for.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#local-variable-declaration\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        },\n                        {\n                            \"include\": \"#punctuation-semicolon\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"foreach-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(foreach)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.foreach.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"(?x)\\n(?:\\n  (\\\\bvar\\\\b)|\\n  (?<type-name>\\n    (?:\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\s+\\n\\\\b(in)\\\\b\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.var.cs\"\n                                },\n                                \"2\": {\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#type\"\n                                        }\n                                    ]\n                                },\n                                \"7\": {\n                                    \"name\": \"entity.name.variable.local.cs\"\n                                },\n                                \"8\": {\n                                    \"name\": \"keyword.control.loop.in.cs\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\":\n                                \"(?x) # match foreach (var (x, y) in ...)\\n(?:\\\\b(var)\\\\b\\\\s*)?\\n(?<tuple>\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\\\s+\\n\\\\b(in)\\\\b\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.var.cs\"\n                                },\n                                \"2\": {\n                                    \"patterns\": [\n                                        {\n                                            \"include\":\n                                                \"#tuple-declaration-deconstruction-element-list\"\n                                        }\n                                    ]\n                                },\n                                \"3\": {\n                                    \"name\": \"keyword.control.loop.in.cs\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"try-statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#try-block\"\n                },\n                {\n                    \"include\": \"#catch-clause\"\n                },\n                {\n                    \"include\": \"#finally-clause\"\n                }\n            ]\n        },\n        \"try-block\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(try)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.try.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"finally-clause\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(finally)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.try.finally.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"catch-clause\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(catch)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.try.catch.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"(?x)\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s*\\n(?:(\\\\g<identifier>)\\\\b)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#type\"\n                                        }\n                                    ]\n                                },\n                                \"6\": {\n                                    \"name\": \"entity.name.variable.local.cs\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#when-clause\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#block\"\n                }\n            ]\n        },\n        \"when-clause\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(when)\\\\b\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.try.when.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"checked-unchecked-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(?:(checked)|(unchecked))\\\\b\\\\s*(?!\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.checked.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.unchecked.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#block\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"lock-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(lock)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.lock.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})|(?=;)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"using-statement\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(using)\\\\b\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.using.cs\"\n                }\n            },\n            \"end\": \"(?=\\\\;|})\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#local-variable-declaration\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#statement\"\n                }\n            ]\n        },\n        \"labeled-statement\": {\n            \"match\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(:)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.label.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                }\n            }\n        },\n        \"local-declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#local-constant-declaration\"\n                },\n                {\n                    \"include\": \"#local-variable-declaration\"\n                },\n                {\n                    \"include\": \"#local-tuple-var-deconstruction\"\n                }\n            ]\n        },\n        \"local-variable-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?:\\n  (?:(\\\\bref)\\\\s+(?:(\\\\breadonly)\\\\s+)?)?(\\\\bvar\\\\b)| # ref local\\n  (?<type-name>\\n    (?:\\n      (?:ref\\\\s+(?:readonly\\\\s+)?)?   # ref local\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\s*\\n(?=,|;|=|\\\\))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.cs\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.cs\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.other.var.cs\"\n                },\n                \"4\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"9\": {\n                    \"name\": \"entity.name.variable.local.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"name\": \"entity.name.variable.local.cs\",\n                    \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"local-constant-declaration\": {\n            \"begin\":\n                \"(?x)\\n(?<const-keyword>\\\\b(?:const)\\\\b)\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\s*\\n(?=,|;|=)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.local.cs\"\n                }\n            },\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"name\": \"entity.name.variable.local.cs\",\n                    \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"local-tuple-var-deconstruction\": {\n            \"begin\":\n                \"(?x) # e.g. var (x, y) = GetPoint();\\n(?:\\\\b(var)\\\\b\\\\s*)\\n(?<tuple>\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\\\s*\\n(?=;|=|\\\\))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.var.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#tuple-declaration-deconstruction-element-list\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"tuple-deconstruction-assignment\": {\n            \"match\": \"(?x)\\n(?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\\\s*\\n(?!=>|==)(?==)\",\n            \"captures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#tuple-deconstruction-element-list\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"tuple-declaration-deconstruction-element-list\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#tuple-declaration-deconstruction-element-list\"\n                },\n                {\n                    \"include\": \"#declaration-expression-tuple\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"match\": \"(?x) # e.g. x\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\\\\s*\\n(?=[,)])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.variable.tuple-element.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"tuple-deconstruction-element-list\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#tuple-deconstruction-element-list\"\n                },\n                {\n                    \"include\": \"#declaration-expression-tuple\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"match\": \"(?x) # e.g. x\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\\\\s*\\n(?=[,)])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.readwrite.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"declaration-expression-local\": {\n            \"match\":\n                \"(?x) # e.g. int x OR var x\\n(?:\\n  \\\\b(var)\\\\b|\\n  (?<type-name>\\n    (?:\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\b\\\\s*\\n(?=[,)\\\\]])\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.var.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.local.cs\"\n                }\n            }\n        },\n        \"declaration-expression-tuple\": {\n            \"match\":\n                \"(?x) # e.g. int x OR var x\\n(?:\\n  \\\\b(var)\\\\b|\\n  (?<type-name>\\n    (?:\\n      (?:\\n        (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n        (?<name-and-type-args> # identifier + type arguments (if any)\\n          \\\\g<identifier>\\\\s*\\n          (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n        )\\n        (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n        (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n      )\\n      (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n      (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n    )\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\\\\b\\\\s*\\n(?=[,)])\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.var.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.tuple-element.cs\"\n                }\n            }\n        },\n        \"checked-unchecked-expression\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(?:(checked)|(unchecked))\\\\b\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.checked.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.unchecked.cs\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"typeof-or-default-expression\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(?:(typeof)|(default))\\\\b\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.typeof.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.default.cs\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"nameof-expression\": {\n            \"begin\": \"(?<!\\\\.)\\\\b(nameof)\\\\b\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.nameof.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"throw-expression\": {\n            \"match\": \"(?<!\\\\.)\\\\b(throw)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.throw.cs\"\n                }\n            }\n        },\n        \"interpolated-string\": {\n            \"name\": \"string.quoted.double.cs\",\n            \"begin\": \"\\\\$\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.cs\"\n                }\n            },\n            \"end\": \"(\\\")|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.cs\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"verbatim-interpolated-string\": {\n            \"name\": \"string.quoted.double.cs\",\n            \"begin\": \"\\\\$@\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.cs\"\n                }\n            },\n            \"end\": \"\\\"(?=[^\\\"])\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#verbatim-string-character-escape\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"interpolation\": {\n            \"name\": \"meta.interpolation.cs\",\n            \"begin\": \"(?<=[^\\\\{])((?:\\\\{\\\\{)*)(\\\\{)(?=[^\\\\{])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"string.quoted.double.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.interpolation.begin.cs\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.interpolation.end.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#boolean-literal\"\n                },\n                {\n                    \"include\": \"#null-literal\"\n                },\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#char-literal\"\n                },\n                {\n                    \"include\": \"#string-literal\"\n                },\n                {\n                    \"include\": \"#verbatim-string-literal\"\n                },\n                {\n                    \"include\": \"#tuple-literal\"\n                }\n            ]\n        },\n        \"boolean-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.boolean.true.cs\",\n                    \"match\": \"(?<!\\\\.)\\\\btrue\\\\b\"\n                },\n                {\n                    \"name\": \"constant.language.boolean.false.cs\",\n                    \"match\": \"(?<!\\\\.)\\\\bfalse\\\\b\"\n                }\n            ]\n        },\n        \"null-literal\": {\n            \"name\": \"constant.language.null.cs\",\n            \"match\": \"(?<!\\\\.)\\\\bnull\\\\b\"\n        },\n        \"numeric-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.numeric.hex.cs\",\n                    \"match\": \"\\\\b0(x|X)[0-9a-fA-F_]+(U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?\\\\b\"\n                },\n                {\n                    \"name\": \"constant.numeric.binary.cs\",\n                    \"match\": \"\\\\b0(b|B)[01_]+(U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?\\\\b\"\n                },\n                {\n                    \"name\": \"constant.numeric.decimal.cs\",\n                    \"match\": \"\\\\b([0-9_]+)?\\\\.[0-9_]+((e|E)[0-9]+)?(F|f|D|d|M|m)?\\\\b\"\n                },\n                {\n                    \"name\": \"constant.numeric.decimal.cs\",\n                    \"match\": \"\\\\b[0-9_]+(e|E)[0-9_]+(F|f|D|d|M|m)?\\\\b\"\n                },\n                {\n                    \"name\": \"constant.numeric.decimal.cs\",\n                    \"match\": \"\\\\b[0-9_]+(F|f|D|d|M|m)\\\\b\"\n                },\n                {\n                    \"name\": \"constant.numeric.decimal.cs\",\n                    \"match\": \"\\\\b[0-9_]+(U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?\\\\b\"\n                }\n            ]\n        },\n        \"char-literal\": {\n            \"name\": \"string.quoted.single.cs\",\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.char.begin.cs\"\n                }\n            },\n            \"end\": \"(\\\\')|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.char.end.cs\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"string-literal\": {\n            \"name\": \"string.quoted.double.cs\",\n            \"begin\": \"(?<!@)\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.cs\"\n                }\n            },\n            \"end\": \"(\\\")|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.cs\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"string-character-escape\": {\n            \"name\": \"constant.character.escape.cs\",\n            \"match\": \"\\\\\\\\.\"\n        },\n        \"verbatim-string-literal\": {\n            \"name\": \"string.quoted.double.cs\",\n            \"begin\": \"@\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.cs\"\n                }\n            },\n            \"end\": \"\\\"(?=[^\\\"])\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#verbatim-string-character-escape\"\n                }\n            ]\n        },\n        \"verbatim-string-character-escape\": {\n            \"name\": \"constant.character.escape.cs\",\n            \"match\": \"\\\"\\\"\"\n        },\n        \"tuple-literal\": {\n            \"begin\": \"(\\\\()(?=.*[:,])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#tuple-literal-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"tuple-literal-element\": {\n            \"begin\": \"(?x)\\n(?:(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(:)\\\\s*)?\\n(?![,)])\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"entity.name.variable.tuple-element.cs\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                }\n            },\n            \"end\": \"(?=[,)])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"expression-operators\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.operator.assignment.compound.cs\",\n                    \"match\": \"\\\\*=|/=|%=|\\\\+=|-=\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.bitwise.cs\",\n                    \"match\": \"\\\\&=|\\\\^=|<<=|>>=|\\\\|=\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.shift.cs\",\n                    \"match\": \"<<|>>\"\n                },\n                {\n                    \"name\": \"keyword.operator.comparison.cs\",\n                    \"match\": \"==|!=\"\n                },\n                {\n                    \"name\": \"keyword.operator.relational.cs\",\n                    \"match\": \"<=|>=|<|>\"\n                },\n                {\n                    \"name\": \"keyword.operator.logical.cs\",\n                    \"match\": \"\\\\!|&&|\\\\|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.cs\",\n                    \"match\": \"\\\\&|~|\\\\^|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.cs\",\n                    \"match\": \"\\\\=\"\n                },\n                {\n                    \"name\": \"keyword.operator.decrement.cs\",\n                    \"match\": \"--\"\n                },\n                {\n                    \"name\": \"keyword.operator.increment.cs\",\n                    \"match\": \"\\\\+\\\\+\"\n                },\n                {\n                    \"name\": \"keyword.operator.arithmetic.cs\",\n                    \"match\": \"%|\\\\*|/|-|\\\\+\"\n                },\n                {\n                    \"name\": \"keyword.operator.null-coalescing.cs\",\n                    \"match\": \"\\\\?\\\\?\"\n                }\n            ]\n        },\n        \"conditional-operator\": {\n            \"begin\": \"(?<!\\\\?)\\\\?(?!\\\\?|\\\\.|\\\\[)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.question-mark.cs\"\n                }\n            },\n            \"end\": \":\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.colon.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"await-expression\": {\n            \"name\": \"keyword.other.await.cs\",\n            \"match\": \"(?!\\\\.)\\\\b(await)\\\\b\"\n        },\n        \"parenthesized-expression\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"initializer-expression\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.open.cs\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.curlybrace.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"identifier\": {\n            \"name\": \"variable.other.readwrite.cs\",\n            \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n        },\n        \"cast-expression\": {\n            \"match\":\n                \"(?x)\\n(\\\\()\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s*\\n(\\\\))(?=\\\\s*@?[_[:alnum:]\\\\(])\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            }\n        },\n        \"as-expression\": {\n            \"match\":\n                \"(?x)\\n(?<!\\\\.)\\\\b(as)\\\\b\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)?\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.as.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"is-expression\": {\n            \"match\":\n                \"(?x)\\n(?<!\\\\.)\\\\b(is)\\\\b\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)?\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.is.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"this-or-base-expression\": {\n            \"match\": \"\\\\b(?:(base)|(this))\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.base.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.this.cs\"\n                }\n            }\n        },\n        \"invocation-expression\": {\n            \"begin\":\n                \"(?x)\\n(?:(\\\\?)\\\\s*)?                                     # preceding null-conditional operator?\\n(?:(\\\\.)\\\\s*)?                                     # preceding dot?\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*                   # method name\\n(?<type-args>\\\\s*<([^<>]|\\\\g<type-args>)+>\\\\s*)?\\\\s* # type arguments\\n(?=\\\\()                                           # open paren of argument list\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.null-conditional.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.accessor.cs\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.function.cs\"\n                },\n                \"4\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-arguments\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?<=\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#argument-list\"\n                }\n            ]\n        },\n        \"element-access-expression\": {\n            \"begin\":\n                \"(?x)\\n(?:(\\\\?)\\\\s*)?                        # preceding null-conditional operator?\\n(?:(\\\\.)\\\\s*)?                        # preceding dot?\\n(?:(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*)? # property name\\n(?:(\\\\?)\\\\s*)?                        # null-conditional operator?\\n(?=\\\\[)                              # open bracket of argument list\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.null-conditional.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.accessor.cs\"\n                },\n                \"3\": {\n                    \"name\": \"variable.other.object.property.cs\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.operator.null-conditional.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\])(?!\\\\s*\\\\[)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#bracketed-argument-list\"\n                }\n            ]\n        },\n        \"member-access-expression\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?x)\\n(?:(\\\\?)\\\\s*)?                   # preceding null-conditional operator?\\n(\\\\.)\\\\s*                        # preceding dot\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\s* # property name\\n(?![_[:alnum:]]|\\\\(|(\\\\?)?\\\\[|<)  # next character is not alpha-numeric, nor a (, [, or <. Also, test for ?[\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.null-conditional.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.cs\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.object.property.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\\\.)?\\\\s*\\n(@?[_[:alpha:]][_[:alnum:]]*)\\n(?<type-params>\\\\s*<([^<>]|\\\\g<type-params>)+>\\\\s*)\\n(?=\\n  (\\\\s*\\\\?)?\\n  \\\\s*\\\\.\\\\s*@?[_[:alpha:]][_[:alnum:]]*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.object.cs\"\n                        },\n                        \"3\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#type-arguments\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(@?[_[:alpha:]][_[:alnum:]]*)\\n(?=\\n  (\\\\s*\\\\?)?\\n  \\\\s*\\\\.\\\\s*@?[_[:alpha:]][_[:alnum:]]*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.object.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"object-creation-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#object-creation-expression-with-parameters\"\n                },\n                {\n                    \"include\": \"#object-creation-expression-with-no-parameters\"\n                }\n            ]\n        },\n        \"object-creation-expression-with-parameters\": {\n            \"begin\":\n                \"(?x)\\n(new)\\\\s+\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s*\\n(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.new.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?<=\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#argument-list\"\n                }\n            ]\n        },\n        \"object-creation-expression-with-no-parameters\": {\n            \"match\":\n                \"(?x)\\n(new)\\\\s+\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s*\\n(?=\\\\{|$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.new.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"array-creation-expression\": {\n            \"begin\":\n                \"(?x)\\n\\\\b(new)\\\\b\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)?\\\\s*\\n(?=\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.new.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            },\n            \"end\": \"(?<=\\\\])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#bracketed-argument-list\"\n                }\n            ]\n        },\n        \"anonymous-object-creation-expression\": {\n            \"begin\": \"\\\\b(new)\\\\b\\\\s*(?=\\\\{|$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.new.cs\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#initializer-expression\"\n                }\n            ]\n        },\n        \"bracketed-parameter-list\": {\n            \"begin\": \"(?=(\\\\[))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.squarebracket.open.cs\"\n                }\n            },\n            \"end\": \"(?=(\\\\]))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.squarebracket.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=\\\\[)\",\n                    \"end\": \"(?=\\\\])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#attribute-section\"\n                        },\n                        {\n                            \"include\": \"#parameter\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        },\n                        {\n                            \"include\": \"#variable-initializer\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"parenthesized-parameter-list\": {\n            \"begin\": \"(\\\\()\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#parameter\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"parameter\": {\n            \"match\":\n                \"(?x)\\n(?:(?:\\\\b(ref|params|out|in|this)\\\\b)\\\\s+)?\\n(?<type-name>\\n  (?:\\n    (?:ref\\\\s+)?   # ref return\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s+\\n(\\\\g<identifier>)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.parameter.cs\"\n                }\n            }\n        },\n        \"argument-list\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#named-argument\"\n                },\n                {\n                    \"include\": \"#argument\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"bracketed-argument-list\": {\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.squarebracket.open.cs\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.squarebracket.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#named-argument\"\n                },\n                {\n                    \"include\": \"#argument\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"named-argument\": {\n            \"begin\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.variable.parameter.cs\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                }\n            },\n            \"end\": \"(?=(,|\\\\)|\\\\]))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#argument\"\n                }\n            ]\n        },\n        \"argument\": {\n            \"patterns\": [\n                {\n                    \"name\": \"storage.modifier.cs\",\n                    \"match\": \"\\\\b(ref|out|in)\\\\b\"\n                },\n                {\n                    \"include\": \"#declaration-expression-local\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"query-expression\": {\n            \"begin\":\n                \"(?x)\\n\\\\b(from)\\\\b\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)?\\n\\\\s+(\\\\g<identifier>)\\\\b\\\\s*\\n\\\\b(in)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.from.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.range-variable.cs\"\n                },\n                \"8\": {\n                    \"name\": \"keyword.query.in.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"query-body\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#let-clause\"\n                },\n                {\n                    \"include\": \"#where-clause\"\n                },\n                {\n                    \"include\": \"#join-clause\"\n                },\n                {\n                    \"include\": \"#orderby-clause\"\n                },\n                {\n                    \"include\": \"#select-clause\"\n                },\n                {\n                    \"include\": \"#group-clause\"\n                }\n            ]\n        },\n        \"let-clause\": {\n            \"begin\": \"(?x)\\n\\\\b(let)\\\\b\\\\s*\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\\\\s*\\n(=)\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.let.cs\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.variable.range-variable.cs\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.operator.assignment.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"where-clause\": {\n            \"begin\": \"(?x)\\n\\\\b(where)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.where.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"join-clause\": {\n            \"begin\":\n                \"(?x)\\n\\\\b(join)\\\\b\\\\s*\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)?\\n\\\\s+(\\\\g<identifier>)\\\\b\\\\s*\\n\\\\b(in)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.join.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.range-variable.cs\"\n                },\n                \"8\": {\n                    \"name\": \"keyword.query.in.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#join-on\"\n                },\n                {\n                    \"include\": \"#join-equals\"\n                },\n                {\n                    \"include\": \"#join-into\"\n                },\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"join-on\": {\n            \"match\": \"\\\\b(on)\\\\b\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.on.cs\"\n                }\n            }\n        },\n        \"join-equals\": {\n            \"match\": \"\\\\b(equals)\\\\b\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.equals.cs\"\n                }\n            }\n        },\n        \"join-into\": {\n            \"match\": \"(?x)\\n\\\\b(into)\\\\b\\\\s*\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.into.cs\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.variable.range-variable.cs\"\n                }\n            }\n        },\n        \"orderby-clause\": {\n            \"begin\": \"\\\\b(orderby)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.orderby.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#ordering-direction\"\n                },\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"ordering-direction\": {\n            \"match\": \"\\\\b(?:(ascending)|(descending))\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.ascending.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.query.descending.cs\"\n                }\n            }\n        },\n        \"select-clause\": {\n            \"begin\": \"\\\\b(select)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.select.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"group-clause\": {\n            \"begin\": \"\\\\b(group)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.group.cs\"\n                }\n            },\n            \"end\": \"(?=;|\\\\))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#group-by\"\n                },\n                {\n                    \"include\": \"#group-into\"\n                },\n                {\n                    \"include\": \"#query-body\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"group-by\": {\n            \"match\": \"\\\\b(by)\\\\b\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.by.cs\"\n                }\n            }\n        },\n        \"group-into\": {\n            \"match\": \"(?x)\\n\\\\b(into)\\\\b\\\\s*\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.query.into.cs\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.variable.range-variable.cs\"\n                }\n            }\n        },\n        \"anonymous-method-expression\": {\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?x)\\n(?:\\\\b(async)\\\\b\\\\s*)?\\n(@?[_[:alpha:]][_[:alnum:]]*)\\\\b\\\\s*\\n(=>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.variable.parameter.cs\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.arrow.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\)|;|}|,)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#block\"\n                        },\n                        {\n                            \"include\": \"#ref-modifier\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?x)\\n(?:\\\\b(async)\\\\b\\\\s*)?\\n(\\\\(.*?\\\\))\\\\s*\\n(=>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.cs\"\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#lambda-parameter-list\"\n                                }\n                            ]\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.arrow.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\)|;|}|,)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#block\"\n                        },\n                        {\n                            \"include\": \"#ref-modifier\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?x)\\n(?:\\\\b(async)\\\\b\\\\s*)?\\n(?:\\\\b(delegate)\\\\b\\\\s*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.delegate.cs\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\)|;|}|,)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parenthesized-parameter-list\"\n                        },\n                        {\n                            \"include\": \"#block\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"lambda-parameter-list\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#attribute-section\"\n                },\n                {\n                    \"include\": \"#lambda-parameter\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"lambda-parameter\": {\n            \"match\":\n                \"(?x)\\n(?:\\\\b(ref|out|in)\\\\b)?\\\\s*\\n(?:(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\\\s+)?\\n(\\\\g<identifier>)\\\\b\\\\s*\\n(?=[,)])\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.cs\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"7\": {\n                    \"name\": \"entity.name.variable.parameter.cs\"\n                }\n            }\n        },\n        \"type\": {\n            \"name\": \"meta.type.cs\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#ref-modifier\"\n                },\n                {\n                    \"include\": \"#readonly-modifier\"\n                },\n                {\n                    \"include\": \"#tuple-type\"\n                },\n                {\n                    \"include\": \"#type-builtin\"\n                },\n                {\n                    \"include\": \"#type-name\"\n                },\n                {\n                    \"include\": \"#type-arguments\"\n                },\n                {\n                    \"include\": \"#type-array-suffix\"\n                },\n                {\n                    \"include\": \"#type-nullable-suffix\"\n                }\n            ]\n        },\n        \"ref-modifier\": {\n            \"name\": \"storage.modifier.cs\",\n            \"match\": \"\\\\b(ref)\\\\b\"\n        },\n        \"readonly-modifier\": {\n            \"name\": \"storage.modifier.cs\",\n            \"match\": \"\\\\b(readonly)\\\\b\"\n        },\n        \"tuple-type\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.open.cs\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#tuple-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"tuple-element\": {\n            \"match\":\n                \"(?x)\\n(?<type-name>\\n  (?:\\n    (?:\\n      (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\\\s*\\\\:\\\\:\\\\s*)? # alias-qualification\\n      (?<name-and-type-args> # identifier + type arguments (if any)\\n        \\\\g<identifier>\\\\s*\\n        (?<type-args>\\\\s*<(?:[^<>]|\\\\g<type-args>)+>\\\\s*)?\\n      )\\n      (?:\\\\s*\\\\.\\\\s*\\\\g<name-and-type-args>)* | # Are there any more names being dotted into?\\n      (?<tuple>\\\\s*\\\\((?:[^\\\\(\\\\)]|\\\\g<tuple>)+\\\\))\\n    )\\n    (?:\\\\s*\\\\?\\\\s*)? # nullable suffix?\\n    (?:\\\\s*\\\\[(?:\\\\s*,\\\\s*)*\\\\]\\\\s*)* # array suffix?\\n  )\\n)\\n(?:(?<tuple-name>\\\\g<identifier>)\\\\b)?\",\n            \"captures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                \"6\": {\n                    \"name\": \"entity.name.variable.tuple-element.cs\"\n                }\n            }\n        },\n        \"type-builtin\": {\n            \"match\":\n                \"\\\\b(bool|byte|char|decimal|double|float|int|long|object|sbyte|short|string|uint|ulong|ushort|void|dynamic)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.type.cs\"\n                }\n            }\n        },\n        \"type-name\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(\\\\:\\\\:)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.alias.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.coloncolon.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(@?[_[:alpha:]][_[:alnum:]]*)\\\\s*(\\\\.)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*(@?[_[:alpha:]][_[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.cs\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"storage.type.cs\",\n                    \"match\": \"@?[_[:alpha:]][_[:alnum:]]*\"\n                }\n            ]\n        },\n        \"type-arguments\": {\n            \"begin\": \"<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.typeparameters.begin.cs\"\n                }\n            },\n            \"end\": \">\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.typeparameters.end.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type-array-suffix\": {\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.squarebracket.open.cs\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.squarebracket.close.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type-nullable-suffix\": {\n            \"match\": \"\\\\?\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.separator.question-mark.cs\"\n                }\n            }\n        },\n        \"operator-assignment\": {\n            \"name\": \"keyword.operator.assignment.cs\",\n            \"match\": \"(?<!=|!)(=)(?!=)\"\n        },\n        \"punctuation-comma\": {\n            \"name\": \"punctuation.separator.comma.cs\",\n            \"match\": \",\"\n        },\n        \"punctuation-semicolon\": {\n            \"name\": \"punctuation.terminator.statement.cs\",\n            \"match\": \";\"\n        },\n        \"punctuation-accessor\": {\n            \"name\": \"punctuation.accessor.cs\",\n            \"match\": \"\\\\.\"\n        },\n        \"preprocessor\": {\n            \"name\": \"meta.preprocessor.cs\",\n            \"begin\": \"^\\\\s*(\\\\#)\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.hash.cs\"\n                }\n            },\n            \"end\": \"(?<=$)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#preprocessor-define-or-undef\"\n                },\n                {\n                    \"include\": \"#preprocessor-if-or-elif\"\n                },\n                {\n                    \"include\": \"#preprocessor-else-or-endif\"\n                },\n                {\n                    \"include\": \"#preprocessor-warning-or-error\"\n                },\n                {\n                    \"include\": \"#preprocessor-region\"\n                },\n                {\n                    \"include\": \"#preprocessor-endregion\"\n                },\n                {\n                    \"include\": \"#preprocessor-load\"\n                },\n                {\n                    \"include\": \"#preprocessor-r\"\n                },\n                {\n                    \"include\": \"#preprocessor-line\"\n                },\n                {\n                    \"include\": \"#preprocessor-pragma-warning\"\n                },\n                {\n                    \"include\": \"#preprocessor-pragma-checksum\"\n                }\n            ]\n        },\n        \"preprocessor-define-or-undef\": {\n            \"match\": \"\\\\b(?:(define)|(undef))\\\\b\\\\s*\\\\b([_[:alpha:]][_[:alnum:]]*)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.define.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.preprocessor.undef.cs\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.variable.preprocessor.symbol.cs\"\n                }\n            }\n        },\n        \"preprocessor-if-or-elif\": {\n            \"begin\": \"\\\\b(?:(if)|(elif))\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.if.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.preprocessor.elif.cs\"\n                }\n            },\n            \"end\": \"(?=$)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#preprocessor-expression\"\n                }\n            ]\n        },\n        \"preprocessor-else-or-endif\": {\n            \"match\": \"\\\\b(?:(else)|(endif))\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.else.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.preprocessor.endif.cs\"\n                }\n            }\n        },\n        \"preprocessor-warning-or-error\": {\n            \"match\": \"\\\\b(?:(warning)|(error))\\\\b\\\\s*(.*)(?=$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.warning.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.preprocessor.error.cs\"\n                },\n                \"3\": {\n                    \"name\": \"string.unquoted.preprocessor.message.cs\"\n                }\n            }\n        },\n        \"preprocessor-load\": {\n            \"begin\": \"\\\\b(load)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.load.cs\"\n                }\n            },\n            \"end\": \"(?=$)\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\"[^\\\"]*\\\\\\\"\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"string.quoted.double.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"preprocessor-r\": {\n            \"begin\": \"\\\\b(r)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.r.cs\"\n                }\n            },\n            \"end\": \"(?=$)\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\"[^\\\"]*\\\\\\\"\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"string.quoted.double.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"preprocessor-region\": {\n            \"match\": \"\\\\b(region)\\\\b\\\\s*(.*)(?=$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.region.cs\"\n                },\n                \"2\": {\n                    \"name\": \"string.unquoted.preprocessor.message.cs\"\n                }\n            }\n        },\n        \"preprocessor-endregion\": {\n            \"match\": \"\\\\b(endregion)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.endregion.cs\"\n                }\n            }\n        },\n        \"preprocessor-line\": {\n            \"begin\": \"\\\\b(line)\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.line.cs\"\n                }\n            },\n            \"end\": \"(?=$)\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(?:(default|hidden))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.preprocessor.default.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.preprocessor.hidden.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"[0-9]+\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"constant.numeric.decimal.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"\\\\\\\"[^\\\"]*\\\\\\\"\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"string.quoted.double.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"preprocessor-pragma-warning\": {\n            \"match\":\n                \"\\\\b(pragma)\\\\b\\\\s*\\\\b(warning)\\\\b\\\\s*\\\\b(?:(disable)|(restore))\\\\b(\\\\s*[0-9]+(?:\\\\s*,\\\\s*[0-9]+)?)?\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.pragma.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.preprocessor.warning.cs\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.preprocessor.disable.cs\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.preprocessor.restore.cs\"\n                },\n                \"5\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"[0-9]+\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"constant.numeric.decimal.cs\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"preprocessor-pragma-checksum\": {\n            \"match\":\n                \"\\\\b(pragma)\\\\b\\\\s*\\\\b(checksum)\\\\b\\\\s*(\\\\\\\"[^\\\"]*\\\\\\\")\\\\s*(\\\\\\\"[^\\\"]*\\\\\\\")\\\\s*(\\\\\\\"[^\\\"]*\\\\\\\")\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.preprocessor.pragma.cs\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.preprocessor.checksum.cs\"\n                },\n                \"3\": {\n                    \"name\": \"string.quoted.double.cs\"\n                },\n                \"4\": {\n                    \"name\": \"string.quoted.double.cs\"\n                },\n                \"5\": {\n                    \"name\": \"string.quoted.double.cs\"\n                }\n            }\n        },\n        \"preprocessor-expression\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.open.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.parenthesis.close.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#preprocessor-expression\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"\\\\b(?:(true)|(false)|([_[:alpha:]][_[:alnum:]]*))\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"constant.language.boolean.true.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.language.boolean.false.cs\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.variable.preprocessor.symbol.cs\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(==|!=)|(\\\\!|&&|\\\\|\\\\|)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.comparison.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.logical.cs\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.block.cs\",\n                    \"begin\": \"/\\\\*\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.cs\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(^\\\\s+)?(?=//)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.cs\"\n                        }\n                    },\n                    \"end\": \"(?=$)\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"comment.block.documentation.cs\",\n                            \"begin\": \"(?<!/)///(?!/)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.cs\"\n                                }\n                            },\n                            \"end\": \"(?=$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#xml-doc-comment\"\n                                }\n                            ]\n                        },\n                        {\n                            \"name\": \"comment.line.double-slash.cs\",\n                            \"begin\": \"(?<!/)//(?:(?!/)|(?=//))\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.cs\"\n                                }\n                            },\n                            \"end\": \"(?=$)\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"xml-doc-comment\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#xml-comment\"\n                },\n                {\n                    \"include\": \"#xml-character-entity\"\n                },\n                {\n                    \"include\": \"#xml-cdata\"\n                },\n                {\n                    \"include\": \"#xml-tag\"\n                }\n            ]\n        },\n        \"xml-tag\": {\n            \"name\": \"meta.tag.cs\",\n            \"begin\":\n                \"(?x)\\n(</?)\\n(\\n  (?:\\n    ([-_[:alnum:]]+)\\n    (:)\\n  )?\\n  ([-_[:alnum:]]+)\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.cs\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.cs\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.namespace.cs\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.separator.colon.cs\"\n                },\n                \"5\": {\n                    \"name\": \"entity.name.tag.localname.cs\"\n                }\n            },\n            \"end\": \"(/?>)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.cs\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#xml-attribute\"\n                }\n            ]\n        },\n        \"xml-attribute\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?x)\\n(?:^|\\\\s+)\\n(\\n  (?:\\n    ([-_[:alnum:]]+)\\n    (:)\\n  )?\\n  ([-_[:alnum:]]+)\\n)\\n(=)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.attribute-name.cs\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.other.attribute-name.namespace.cs\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.separator.colon.cs\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.other.attribute-name.localname.cs\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.separator.equals.cs\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#xml-string\"\n                }\n            ]\n        },\n        \"xml-cdata\": {\n            \"name\": \"string.unquoted.cdata.cs\",\n            \"begin\": \"<!\\\\[CDATA\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.cs\"\n                }\n            },\n            \"end\": \"\\\\]\\\\]>\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.cs\"\n                }\n            }\n        },\n        \"xml-string\": {\n            \"patterns\": [\n                {\n                    \"name\": \"string.quoted.single.cs\",\n                    \"begin\": \"\\\\'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#xml-character-entity\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.quoted.double.cs\",\n                    \"begin\": \"\\\\\\\"\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.cs\"\n                        }\n                    },\n                    \"end\": \"\\\\\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.cs\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#xml-character-entity\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"xml-character-entity\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.entity.cs\",\n                    \"match\":\n                        \"(?x)\\n(&)\\n(\\n  (?:[[:alpha:]:_][[:alnum:]:_.-]*)|\\n  (?:\\\\#[[:digit:]]+)|\\n  (?:\\\\#x[[:xdigit:]]+)\\n)\\n(;)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.constant.cs\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.constant.cs\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"invalid.illegal.bad-ampersand.cs\",\n                    \"match\": \"&\"\n                }\n            ]\n        },\n        \"xml-comment\": {\n            \"name\": \"comment.block.cs\",\n            \"begin\": \"<!--\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.cs\"\n                }\n            },\n            \"end\": \"-->\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.cs\"\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/css/syntaxes/css.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-css/blob/master/grammars/css.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-css/commit/ec289867164a34fce48a69776b7f8dc380e3dc37\",\n    \"scopeName\": \"source.css\",\n    \"name\": \"CSS\",\n    \"fileTypes\": [\"css\", \"css.erb\"],\n    \"firstLineMatch\":\n        \"(?xi)\\n# Emacs modeline\\n-\\\\*-(?:\\\\s*(?=[^:;\\\\s]+\\\\s*-\\\\*-)|(?:.*?[;\\\\s]|(?<=-\\\\*-))mode\\\\s*:\\\\s*)\\n  css\\n(?=[\\\\s;]|(?<![-*])-\\\\*-).*?-\\\\*-\\n|\\n# Vim modeline\\n(?:(?:\\\\s|^)vi(?:m[<=>]?\\\\d+|m)?|\\\\sex)(?=:(?=\\\\s*set?\\\\s[^\\\\n:]+:)|:(?!\\\\s*set?\\\\s))(?:(?:\\\\s|\\\\s*:\\\\s*)\\\\w*(?:\\\\s*=(?:[^\\\\n\\\\\\\\\\\\s]|\\\\\\\\.)*)?)*[\\\\s:](?:filetype|ft|syntax)\\\\s*=\\n  css\\n(?=\\\\s|:|$)\",\n    \"patterns\": [\n        {\n            \"include\": \"#comment-block\"\n        },\n        {\n            \"include\": \"#escapes\"\n        },\n        {\n            \"include\": \"#combinators\"\n        },\n        {\n            \"include\": \"#selector\"\n        },\n        {\n            \"include\": \"#at-rules\"\n        },\n        {\n            \"include\": \"#rule-list\"\n        }\n    ],\n    \"repository\": {\n        \"at-rules\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\A(?:\\\\xEF\\\\xBB\\\\xBF)?(?i:(?=\\\\s*@charset\\\\b))\",\n                    \"end\": \";|(?=$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.terminator.rule.css\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.charset.css\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"invalid.illegal.not-lowercase.charset.css\"\n                                },\n                                \"2\": {\n                                    \"name\": \"invalid.illegal.leading-whitespace.charset.css\"\n                                },\n                                \"3\": {\n                                    \"name\": \"invalid.illegal.no-whitespace.charset.css\"\n                                },\n                                \"4\": {\n                                    \"name\": \"invalid.illegal.whitespace.charset.css\"\n                                },\n                                \"5\": {\n                                    \"name\": \"invalid.illegal.not-double-quoted.charset.css\"\n                                },\n                                \"6\": {\n                                    \"name\": \"invalid.illegal.unclosed-string.charset.css\"\n                                },\n                                \"7\": {\n                                    \"name\": \"invalid.illegal.unexpected-characters.charset.css\"\n                                }\n                            },\n                            \"match\":\n                                \"(?x)        # Possible errors:\\n\\\\G\\n((?!@charset)@\\\\w+)   # Not lowercase (@charset is case-sensitive)\\n|\\n\\\\G(\\\\s+)             # Preceding whitespace\\n|\\n(@charset\\\\S[^;]*)    # No whitespace after @charset\\n|\\n(?<=@charset)         # Before quoted charset name\\n(\\\\x20{2,}|\\\\t+)      # More than one space used, or a tab\\n|\\n(?<=@charset\\\\x20)    # Beginning of charset name\\n([^\\\";]+)              # Not double-quoted\\n|\\n(\\\"[^\\\"]+$)             # Unclosed quote\\n|\\n(?<=\\\")                # After charset name\\n([^;]+)               # Unexpected junk instead of semicolon\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.control.at-rule.charset.css\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.keyword.css\"\n                                }\n                            },\n                            \"match\": \"((@)charset)(?=\\\\s)\"\n                        },\n                        {\n                            \"begin\": \"\\\"\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.begin.css\"\n                                }\n                            },\n                            \"end\": \"\\\"|$\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.end.css\"\n                                }\n                            },\n                            \"name\": \"string.quoted.double.css\",\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"(?:\\\\G|^)(?=(?:[^\\\"])+$)\",\n                                    \"end\": \"$\",\n                                    \"name\": \"invalid.illegal.unclosed.string.css\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((@)import)(?:\\\\s+|$|(?=['\\\"]|/\\\\*))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.import.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.css\"\n                        }\n                    },\n                    \"end\": \";\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.terminator.rule.css\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.import.css\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G\\\\s*(?=/\\\\*)\",\n                            \"end\": \"(?<=\\\\*/)\\\\s*\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment-block\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#string\"\n                        },\n                        {\n                            \"include\": \"#url\"\n                        },\n                        {\n                            \"include\": \"#media-query-list\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((@)font-face)(?=\\\\s*|{|/\\\\*|$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.font-face.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.css\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\G)\",\n                    \"name\": \"meta.at-rule.font-face.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        },\n                        {\n                            \"include\": \"#rule-list\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(@)page(?=[\\\\s:{]|/\\\\*|$)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.at-rule.page.css\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.keyword.css\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s*($|[:{;]))\",\n                    \"name\": \"meta.at-rule.page.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#rule-list\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?=@media(\\\\s|\\\\(|/\\\\*|$))\",\n                    \"end\": \"(?<=})(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?i)\\\\G(@)media\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.control.at-rule.media.css\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.keyword.css\"\n                                }\n                            },\n                            \"end\": \"(?=\\\\s*[{;])\",\n                            \"name\": \"meta.at-rule.media.header.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#media-query-list\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.media.begin.bracket.curly.css\"\n                                }\n                            },\n                            \"end\": \"}\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.media.end.bracket.curly.css\"\n                                }\n                            },\n                            \"name\": \"meta.at-rule.media.body.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?=@counter-style([\\\\s'\\\"{;]|/\\\\*|$))\",\n                    \"end\": \"(?<=})(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?i)\\\\G(@)counter-style\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.control.at-rule.counter-style.css\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.keyword.css\"\n                                }\n                            },\n                            \"end\": \"(?=\\\\s*{)\",\n                            \"name\": \"meta.at-rule.counter-style.header.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment-block\"\n                                },\n                                {\n                                    \"include\": \"#escapes\"\n                                },\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"patterns\": [\n                                                {\n                                                    \"include\": \"#escapes\"\n                                                }\n                                            ]\n                                        }\n                                    },\n                                    \"match\":\n                                        \"(?x)\\n(?:[-a-zA-Z_]    | [^\\\\x00-\\\\x7F])     # First letter\\n(?:[-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]      # Remainder of identifier\\n  |\\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n)*\",\n                                    \"name\": \"variable.parameter.style-name.css\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.section.property-list.begin.bracket.curly.css\"\n                                }\n                            },\n                            \"end\": \"}\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.section.property-list.end.bracket.curly.css\"\n                                }\n                            },\n                            \"name\": \"meta.at-rule.counter-style.body.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment-block\"\n                                },\n                                {\n                                    \"include\": \"#escapes\"\n                                },\n                                {\n                                    \"include\": \"#rule-list-innards\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?=@document([\\\\s'\\\"{;]|/\\\\*|$))\",\n                    \"end\": \"(?<=})(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?i)\\\\G(@)document\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.control.at-rule.document.css\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.keyword.css\"\n                                }\n                            },\n                            \"end\": \"(?=\\\\s*[{;])\",\n                            \"name\": \"meta.at-rule.document.header.css\",\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"(?i)(?<![\\\\w-])(url-prefix|domain|regexp)(\\\\()\",\n                                    \"beginCaptures\": {\n                                        \"1\": {\n                                            \"name\": \"support.function.document-rule.css\"\n                                        },\n                                        \"2\": {\n                                            \"name\":\n                                                \"punctuation.section.function.begin.bracket.round.css\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\)\",\n                                    \"endCaptures\": {\n                                        \"0\": {\n                                            \"name\":\n                                                \"punctuation.section.function.end.bracket.round.css\"\n                                        }\n                                    },\n                                    \"name\": \"meta.function.document-rule.css\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#string\"\n                                        },\n                                        {\n                                            \"include\": \"#comment-block\"\n                                        },\n                                        {\n                                            \"include\": \"#escapes\"\n                                        },\n                                        {\n                                            \"match\": \"[^'\\\")\\\\s]+\",\n                                            \"name\": \"variable.parameter.document-rule.css\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"include\": \"#url\"\n                                },\n                                {\n                                    \"include\": \"#commas\"\n                                },\n                                {\n                                    \"include\": \"#comment-block\"\n                                },\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.document.begin.bracket.curly.css\"\n                                }\n                            },\n                            \"end\": \"}\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.document.end.bracket.curly.css\"\n                                }\n                            },\n                            \"name\": \"meta.at-rule.document.body.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?=@(?:-(?:webkit|moz|o|ms)-)?keyframes([\\\\s'\\\"{;]|/\\\\*|$))\",\n                    \"end\": \"(?<=})(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?i)\\\\G(@)(?:-(?:webkit|moz|o|ms)-)?keyframes\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.control.at-rule.keyframes.css\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.keyword.css\"\n                                }\n                            },\n                            \"end\": \"(?=\\\\s*{)\",\n                            \"name\": \"meta.at-rule.keyframes.header.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment-block\"\n                                },\n                                {\n                                    \"include\": \"#escapes\"\n                                },\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"patterns\": [\n                                                {\n                                                    \"include\": \"#escapes\"\n                                                }\n                                            ]\n                                        }\n                                    },\n                                    \"match\":\n                                        \"(?x)\\n(?:[-a-zA-Z_]    | [^\\\\x00-\\\\x7F])     # First letter\\n(?:[-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]      # Remainder of identifier\\n  |\\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n)*\",\n                                    \"name\": \"variable.parameter.keyframe-list.css\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.keyframes.begin.bracket.curly.css\"\n                                }\n                            },\n                            \"end\": \"}\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.keyframes.end.bracket.curly.css\"\n                                }\n                            },\n                            \"name\": \"meta.at-rule.keyframes.body.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment-block\"\n                                },\n                                {\n                                    \"include\": \"#escapes\"\n                                },\n                                {\n                                    \"captures\": {\n                                        \"1\": {\n                                            \"name\": \"entity.other.keyframe-offset.css\"\n                                        },\n                                        \"2\": {\n                                            \"name\": \"entity.other.keyframe-offset.percentage.css\"\n                                        }\n                                    },\n                                    \"match\":\n                                        \"(?xi)\\n(?<![\\\\w-]) (from|to) (?![\\\\w-])         # Keywords for 0% | 100%\\n|\\n([-+]?(?:\\\\d+(?:\\\\.\\\\d+)?|\\\\.\\\\d+)%)     # Percentile value\"\n                                },\n                                {\n                                    \"include\": \"#rule-list\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?=@supports(\\\\s|\\\\(|/\\\\*|$))\",\n                    \"end\": \"(?<=})(?!\\\\G)|(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?i)\\\\G(@)supports\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.control.at-rule.supports.css\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.keyword.css\"\n                                }\n                            },\n                            \"end\": \"(?=\\\\s*[{;])\",\n                            \"name\": \"meta.at-rule.supports.header.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#feature-query-operators\"\n                                },\n                                {\n                                    \"include\": \"#feature-query\"\n                                },\n                                {\n                                    \"include\": \"#comment-block\"\n                                },\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.supports.begin.bracket.curly.css\"\n                                }\n                            },\n                            \"end\": \"}\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.supports.end.bracket.curly.css\"\n                                }\n                            },\n                            \"name\": \"meta.at-rule.supports.body.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((@)viewport)(?=[\\\\s'\\\"{;]|/\\\\*|$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.viewport.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.css\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s*[@{;])\",\n                    \"name\": \"meta.at-rule.viewport.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((@)font-feature-values)(?=[\\\\s'\\\"{;]|/\\\\*|$)\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.font-feature-values.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.css\"\n                        }\n                    },\n                    \"contentName\": \"variable.parameter.font-name.css\",\n                    \"end\": \"(?=\\\\s*[@{;])\",\n                    \"name\": \"meta.at-rule.font-features.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#font-features\"\n                },\n                {\n                    \"begin\": \"(?i)((@)namespace)(?=[\\\\s'\\\";]|/\\\\*|$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.namespace.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.css\"\n                        }\n                    },\n                    \"end\": \";|(?=[@{])\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.terminator.rule.css\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.namespace.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#url\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#comment-block\"\n                                        }\n                                    ]\n                                },\n                                \"2\": {\n                                    \"name\": \"entity.name.function.namespace-prefix.css\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escapes\"\n                                        }\n                                    ]\n                                }\n                            },\n                            \"match\":\n                                \"(?xi)\\n(?:\\\\G|^|(?<=\\\\s))\\n(?=\\n  (?<=\\\\s|^)                             # Starts with whitespace\\n  (?:[-a-zA-Z_]|[^\\\\x00-\\\\x7F])          # Then a valid identifier character\\n  |\\n  \\\\s*                                   # Possible adjoining whitespace\\n  /\\\\*(?:[^*]|\\\\*[^/])*\\\\*/              # Injected comment\\n)\\n(.*?)                                    # Grouped to embed #comment-block\\n(\\n  (?:[-a-zA-Z_]    | [^\\\\x00-\\\\x7F])     # First letter\\n  (?:[-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]      # Remainder of identifier\\n    |\\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n  )*\\n)\"\n                        },\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"color-keywords\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?i)(?<![\\\\w-])(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)(?![\\\\w-])\",\n                    \"name\": \"support.constant.color.w3c-standard-color-name.css\"\n                },\n                {\n                    \"match\":\n                        \"(?xi) (?<![\\\\w-])\\n(aliceblue|antiquewhite|aquamarine|azure|beige|bisque|blanchedalmond|blueviolet|brown|burlywood\\n|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan\\n|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange\\n|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise\\n|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen\\n|gainsboro|ghostwhite|gold|goldenrod|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki\\n|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow\\n|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray\\n|lightslategrey|lightsteelblue|lightyellow|limegreen|linen|magenta|mediumaquamarine|mediumblue\\n|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise\\n|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|oldlace|olivedrab|orangered\\n|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum\\n|powderblue|rebeccapurple|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell\\n|sienna|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|thistle|tomato\\n|transparent|turquoise|violet|wheat|whitesmoke|yellowgreen)\\n(?![\\\\w-])\",\n                    \"name\": \"support.constant.color.w3c-extended-color-name.css\"\n                },\n                {\n                    \"match\": \"(?i)(?<![\\\\w-])currentColor(?![\\\\w-])\",\n                    \"name\": \"support.constant.color.current.css\"\n                },\n                {\n                    \"match\":\n                        \"(?xi) (?<![\\\\w-])\\n(ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|ButtonHighlight|ButtonShadow\\n|ButtonText|CaptionText|GrayText|Highlight|HighlightText|InactiveBorder|InactiveCaption\\n|InactiveCaptionText|InfoBackground|InfoText|Menu|MenuText|Scrollbar|ThreeDDarkShadow\\n|ThreeDFace|ThreeDHighlight|ThreeDLightShadow|ThreeDShadow|Window|WindowFrame|WindowText)\\n(?![\\\\w-])\",\n                    \"name\": \"invalid.deprecated.color.system.css\"\n                }\n            ]\n        },\n        \"combinators\": {\n            \"patterns\": [\n                {\n                    \"match\": \"/deep/|>>>\",\n                    \"name\": \"invalid.deprecated.combinator.css\"\n                },\n                {\n                    \"match\": \">>|>|\\\\+|~\",\n                    \"name\": \"keyword.operator.combinator.css\"\n                }\n            ]\n        },\n        \"commas\": {\n            \"match\": \",\",\n            \"name\": \"punctuation.separator.list.comma.css\"\n        },\n        \"comment-block\": {\n            \"begin\": \"/\\\\*\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.begin.css\"\n                }\n            },\n            \"end\": \"\\\\*/\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.end.css\"\n                }\n            },\n            \"name\": \"comment.block.css\"\n        },\n        \"escapes\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\[0-9a-fA-F]{1,6}\",\n                    \"name\": \"constant.character.escape.codepoint.css\"\n                },\n                {\n                    \"begin\": \"\\\\\\\\$\\\\s*\",\n                    \"end\": \"^(?<!\\\\G)\",\n                    \"name\": \"constant.character.escape.newline.css\"\n                },\n                {\n                    \"match\": \"\\\\\\\\.\",\n                    \"name\": \"constant.character.escape.css\"\n                }\n            ]\n        },\n        \"feature-query\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.condition.begin.bracket.round.css\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.condition.end.bracket.round.css\"\n                }\n            },\n            \"name\": \"meta.feature-query.css\",\n            \"patterns\": [\n                {\n                    \"include\": \"#feature-query-operators\"\n                },\n                {\n                    \"include\": \"#feature-query\"\n                }\n            ]\n        },\n        \"feature-query-operators\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?i)(?<=[\\\\s()]|^|\\\\*/)(and|not|or)(?=[\\\\s()]|/\\\\*|$)\",\n                    \"name\": \"keyword.operator.logical.feature.$1.css\"\n                },\n                {\n                    \"include\": \"#rule-list-innards\"\n                }\n            ]\n        },\n        \"font-features\": {\n            \"begin\":\n                \"(?xi)\\n((@)(annotation|character-variant|ornaments|styleset|stylistic|swash))\\n(?=[\\\\s@'\\\"{;]|/\\\\*|$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.${3:/downcase}.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.css\"\n                }\n            },\n            \"end\": \"(?<=})\",\n            \"name\": \"meta.at-rule.${3:/downcase}.css\",\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.property-list.begin.bracket.curly.css\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.property-list.end.bracket.curly.css\"\n                        }\n                    },\n                    \"name\": \"meta.property-list.font-feature.css\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"0\": {\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escapes\"\n                                        }\n                                    ]\n                                }\n                            },\n                            \"match\":\n                                \"(?x)\\n(?: [-a-zA-Z_]    | [^\\\\x00-\\\\x7F] )   # First letter\\n(?: [-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]     # Remainder of identifier\\n  | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n)*\",\n                            \"name\": \"variable.font-feature.css\"\n                        },\n                        {\n                            \"include\": \"#rule-list-innards\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"functions\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?i)(?<![\\\\w-])(calc)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.calc.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.calc.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"[*/]|(?<=\\\\s|^)[-+](?=\\\\s|$)\",\n                            \"name\": \"keyword.operator.arithmetic.css\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?<![\\\\w-])(rgba?|hsla?)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.misc.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.color.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?xi) (?<![\\\\w-])\\n(\\n  (?:-webkit-|-moz-|-o-)?    # Accept prefixed/historical variants\\n  (?:repeating-)?            # \\\"Repeating\\\"-type gradient\\n  (?:linear|radial|conic)    # Shape\\n  -gradient\\n)\\n(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.gradient.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.gradient.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"(?i)(?<![\\\\w-])(from|to|at)(?![\\\\w-])\",\n                            \"name\": \"keyword.operator.gradient.css\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?<![\\\\w-])(-webkit-gradient)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"invalid.deprecated.gradient.function.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.gradient.invalid.deprecated.gradient.css\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?i)(?<![\\\\w-])(from|to|color-stop)(\\\\()\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"invalid.deprecated.function.css\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                                }\n                            },\n                            \"end\": \"\\\\)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#property-values\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?xi) (?<![\\\\w-])\\n(annotation|attr|blur|brightness|character-variant|contrast|counters?\\n|cross-fade|drop-shadow|element|fit-content|format|grayscale|hue-rotate\\n|image-set|invert|local|minmax|opacity|ornaments|repeat|saturate|sepia\\n|styleset|stylistic|swash|symbols)\\n(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.misc.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.misc.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"(?i)(?<=[,\\\\s\\\"]|\\\\*/|^)\\\\d+x(?=[\\\\s,\\\"')]|/\\\\*|$)\",\n                            \"name\": \"constant.numeric.other.density.css\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        },\n                        {\n                            \"match\": \"[^'\\\"),\\\\s]+\",\n                            \"name\": \"variable.parameter.misc.css\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?<![\\\\w-])(circle|ellipse|inset|polygon|rect)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.shape.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.shape.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"(?i)(?<=\\\\s|^|\\\\*/)(at|round)(?=\\\\s|/\\\\*|$)\",\n                            \"name\": \"keyword.operator.shape.css\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(?<![\\\\w-])(cubic-bezier|steps)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.timing-function.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.timing-function.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"(?i)(?<![\\\\w-])(start|end)(?=\\\\s*\\\\)|$)\",\n                            \"name\": \"support.constant.step-direction.css\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?xi) (?<![\\\\w-])\\n( (?:translate|scale|rotate)(?:[XYZ]|3D)?\\n| matrix(?:3D)?\\n| skew[XY]?\\n| perspective\\n)\\n(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.transform.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#url\"\n                },\n                {\n                    \"begin\": \"(?i)(?<![\\\\w-])(var)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.misc.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"name\": \"meta.function.variable.css\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"variable.argument.css\",\n                            \"match\":\n                                \"(?x)\\n--\\n(?:[-a-zA-Z_]    | [^\\\\x00-\\\\x7F])     # First letter\\n(?:[-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]      # Remainder of identifier\\n  |\\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n)*\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"functional-pseudo-classes\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?i)((:)dir)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.attribute-name.pseudo-class.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        },\n                        {\n                            \"match\": \"(?i)(?<![\\\\w-])(ltr|rtl)(?![\\\\w-])\",\n                            \"name\": \"support.constant.text-direction.css\"\n                        },\n                        {\n                            \"include\": \"#property-value\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((:)lang)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.attribute-name.pseudo-class.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"(?<=[(,\\\\s])[a-zA-Z]+(-[a-zA-Z0-9]*|\\\\\\\\(?:[0-9a-fA-F]{1,6}|.))*(?=[),\\\\s])\",\n                            \"name\": \"support.constant.language-range.css\"\n                        },\n                        {\n                            \"begin\": \"\\\"\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.begin.css\"\n                                }\n                            },\n                            \"end\": \"\\\"\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.end.css\"\n                                }\n                            },\n                            \"name\": \"string.quoted.double.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                },\n                                {\n                                    \"match\": \"(?<=[\\\"\\\\s])[a-zA-Z*]+(-[a-zA-Z0-9*]*)*(?=[\\\"\\\\s])\",\n                                    \"name\": \"support.constant.language-range.css\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"'\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.begin.css\"\n                                }\n                            },\n                            \"end\": \"'\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.end.css\"\n                                }\n                            },\n                            \"name\": \"string.quoted.single.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                },\n                                {\n                                    \"match\": \"(?<=['\\\\s])[a-zA-Z*]+(-[a-zA-Z0-9*]*)*(?=['\\\\s])\",\n                                    \"name\": \"support.constant.language-range.css\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#commas\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((:)(?:not|has|matches))(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.attribute-name.pseudo-class.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#selector-innards\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)((:)nth-(?:last-)?(?:child|of-type))(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.attribute-name.pseudo-class.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"(?i)[+-]?(\\\\d+n?|n)(\\\\s*[+-]\\\\s*\\\\d+)?\",\n                            \"name\": \"constant.numeric.css\"\n                        },\n                        {\n                            \"match\": \"(?i)even|odd\",\n                            \"name\": \"support.constant.parity.css\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"media-features\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"support.type.property-name.media.css\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.deprecated.media.css\"\n                },\n                \"3\": {\n                    \"name\": \"support.type.vendored.property-name.media.css\"\n                }\n            },\n            \"match\":\n                \"(?xi)\\n(?<=^|\\\\s|\\\\(|\\\\*/)           # Preceded by whitespace, bracket or comment\\n(?:\\n  # Standardised features\\n  (\\n    (?:min-|max-)?            # Range features\\n    (?: height\\n      | width\\n      | aspect-ratio\\n      | color\\n      | color-index\\n      | monochrome\\n      | resolution\\n    )\\n    | grid                    # Discrete features\\n    | scan\\n    | orientation\\n    | display-mode\\n  )\\n  |\\n  # Deprecated features\\n  (\\n    (?:min-|max-)?            # Deprecated in Media Queries 4\\n    device-\\n    (?: height\\n      | width\\n      | aspect-ratio\\n    )\\n  )\\n  |\\n  # Vendor extensions\\n  (\\n    (?:\\n      # Spec-compliant syntax\\n      [-_]\\n      (?: webkit              # Webkit/Blink\\n        | apple|khtml         # Webkit aliases\\n        | epub                # ePub3\\n        | moz                 # Gecko\\n        | ms                  # Microsoft\\n        | o                   # Presto (pre-Opera 15)\\n        | xv|ah|rim|atsc|     # Less common vendors\\n          hp|tc|wap|ro\\n      )\\n      |\\n      # Non-standard prefixes\\n      (?: mso                 # Microsoft Office\\n        | prince              # YesLogic\\n      )\\n    )\\n    -\\n    [\\\\w-]+                   # Feature name\\n    (?=                       # Terminates correctly\\n      \\\\s*                    # Possible whitespace\\n      (?:                     # Possible injected comment\\n        /\\\\*\\n        (?:[^*]|\\\\*[^/])*\\n        \\\\*/\\n      )?\\n      \\\\s*\\n      [:)]                    # Ends with a colon or closed bracket\\n    )\\n  )\\n)\\n(?=\\\\s|$|[><:=]|\\\\)|/\\\\*)     # Terminates cleanly\"\n        },\n        \"media-feature-keywords\": {\n            \"match\":\n                \"(?xi)\\n(?<=^|\\\\s|:|\\\\*/)\\n(?: portrait                  # Orientation\\n  | landscape\\n  | progressive               # Scan types\\n  | interlace\\n  | fullscreen                # Display modes\\n  | standalone\\n  | minimal-ui\\n  | browser\\n)\\n(?=\\\\s|\\\\)|$)\",\n            \"name\": \"support.constant.property-value.css\"\n        },\n        \"media-query\": {\n            \"begin\": \"\\\\G\",\n            \"end\": \"(?=\\\\s*[{;])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment-block\"\n                },\n                {\n                    \"include\": \"#escapes\"\n                },\n                {\n                    \"include\": \"#media-types\"\n                },\n                {\n                    \"match\": \"(?i)(?<=\\\\s|^|,|\\\\*/)(only|not)(?=\\\\s|{|/\\\\*|$)\",\n                    \"name\": \"keyword.operator.logical.$1.media.css\"\n                },\n                {\n                    \"match\": \"(?i)(?<=\\\\s|^|\\\\*/|\\\\))and(?=\\\\s|/\\\\*|$)\",\n                    \"name\": \"keyword.operator.logical.and.media.css\"\n                },\n                {\n                    \"match\": \",(?:(?:\\\\s*,)+|(?=\\\\s*[;){]))\",\n                    \"name\": \"invalid.illegal.comma.css\"\n                },\n                {\n                    \"include\": \"#commas\"\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#media-features\"\n                        },\n                        {\n                            \"include\": \"#media-feature-keywords\"\n                        },\n                        {\n                            \"match\": \":\",\n                            \"name\": \"punctuation.separator.key-value.css\"\n                        },\n                        {\n                            \"match\": \">=|<=|=|<|>\",\n                            \"name\": \"keyword.operator.comparison.css\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"constant.numeric.css\"\n                                },\n                                \"2\": {\n                                    \"name\": \"keyword.operator.arithmetic.css\"\n                                },\n                                \"3\": {\n                                    \"name\": \"constant.numeric.css\"\n                                }\n                            },\n                            \"match\": \"(\\\\d+)\\\\s*(/)\\\\s*(\\\\d+)\",\n                            \"name\": \"meta.ratio.css\"\n                        },\n                        {\n                            \"include\": \"#numeric-values\"\n                        },\n                        {\n                            \"include\": \"#comment-block\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"media-query-list\": {\n            \"begin\": \"(?=\\\\s*[^{;])\",\n            \"end\": \"(?=\\\\s*[{;])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#media-query\"\n                }\n            ]\n        },\n        \"media-types\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"support.constant.media.css\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.deprecated.constant.media.css\"\n                }\n            },\n            \"match\":\n                \"(?xi)\\n(?<=^|\\\\s|,|\\\\*/)\\n(?:\\n  # Valid media types\\n  (all|print|screen|speech)\\n  |\\n  # Deprecated in Media Queries 4: http://dev.w3.org/csswg/mediaqueries/#media-types\\n  (aural|braille|embossed|handheld|projection|tty|tv)\\n)\\n(?=$|[{,\\\\s;]|/\\\\*)\"\n        },\n        \"numeric-values\": {\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.constant.css\"\n                        }\n                    },\n                    \"match\": \"(#)(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\\\\b\",\n                    \"name\": \"constant.other.color.rgb-value.hex.css\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.unit.percentage.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.unit.${2:/downcase}.css\"\n                        }\n                    },\n                    \"match\":\n                        \"(?xi) (?<![\\\\w-])\\n[-+]?                               # Sign indicator\\n\\n(?:                                 # Numerals\\n    [0-9]+ (?:\\\\.[0-9]+)?           # Integer/float with leading digits\\n  | \\\\.[0-9]+                       # Float without leading digits\\n)\\n\\n(?:                                 # Scientific notation\\n  (?<=[0-9])                        # Exponent must follow a digit\\n  E                                 # Exponent indicator\\n  [-+]?                             # Possible sign indicator\\n  [0-9]+                            # Exponent value\\n)?\\n\\n(?:                                 # Possible unit for data-type:\\n  (%)                               # - Percentage\\n  | ( deg|grad|rad|turn             # - Angle\\n    | Hz|kHz                        # - Frequency\\n    | ch|cm|em|ex|fr|in|mm|mozmm|   # - Length\\n      pc|pt|px|q|rem|vh|vmax|vmin|\\n      vw\\n    | dpi|dpcm|dppx                 # - Resolution\\n    | s|ms                          # - Time\\n    )\\n  \\\\b                               # Boundary checking intentionally lax to\\n)?                                  # facilitate embedding in CSS-like grammars\",\n                    \"name\": \"constant.numeric.css\"\n                }\n            ]\n        },\n        \"property-keywords\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?xi) (?<![\\\\w-])\\n(above|absolute|active|add|additive|after-edge|alias|all|all-petite-caps|all-scroll|all-small-caps|alpha|alphabetic|alternate|alternate-reverse\\n|always|antialiased|auto|auto-pos|available|avoid|avoid-column|avoid-page|avoid-region|backwards|balance|baseline|before-edge|below|bevel\\n|bidi-override|blink|block|block-axis|block-start|block-end|bold|bolder|border|border-box|both|bottom|bottom-outside|break-all|break-word|bullets\\n|butt|capitalize|caption|cell|center|central|char|circle|clip|clone|close-quote|closest-corner|closest-side|col-resize|collapse|color|color-burn\\n|color-dodge|column|column-reverse|common-ligatures|compact|condensed|contain|content|content-box|contents|context-menu|contextual|copy|cover\\n|crisp-edges|crispEdges|crosshair|cyclic|darken|dashed|decimal|default|dense|diagonal-fractions|difference|digits|disabled|disc|discretionary-ligatures\\n|distribute|distribute-all-lines|distribute-letter|distribute-space|dot|dotted|double|double-circle|downleft|downright|e-resize|each-line|ease|ease-in\\n|ease-in-out|ease-out|economy|ellipse|ellipsis|embed|end|evenodd|ew-resize|exact|exclude|exclusion|expanded|extends|extra-condensed|extra-expanded\\n|fallback|farthest-corner|farthest-side|fill|fill-available|fill-box|filled|fit-content|fixed|flat|flex|flex-end|flex-start|flip|forwards|freeze\\n|from-image|full-width|geometricPrecision|georgian|grab|grabbing|grayscale|grid|groove|hand|hanging|hard-light|help|hidden|hide\\n|historical-forms|historical-ligatures|horizontal|horizontal-tb|hue|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space\\n|ideographic|inactive|infinite|inherit|initial|inline|inline-axis|inline-block|inline-end|inline-flex|inline-grid|inline-list-item|inline-start\\n|inline-table|inset|inside|inter-character|inter-ideograph|inter-word|intersect|invert|isolate|isolate-override|italic|jis04|jis78|jis83\\n|jis90|justify|justify-all|kannada|keep-all|landscape|large|larger|left|lighten|lighter|line|line-edge|line-through|linear|linearRGB\\n|lining-nums|list-item|local|loose|lowercase|lr|lr-tb|ltr|luminance|luminosity|main-size|mandatory|manipulation|manual|margin-box|match-parent\\n|match-source|mathematical|max-content|medium|menu|message-box|middle|min-content|miter|mixed|move|multiply|n-resize|narrower|ne-resize\\n|nearest-neighbor|nesw-resize|newspaper|no-change|no-clip|no-close-quote|no-common-ligatures|no-contextual|no-discretionary-ligatures\\n|no-drop|no-historical-ligatures|no-open-quote|no-repeat|none|nonzero|normal|not-allowed|nowrap|ns-resize|numbers|numeric|nw-resize|nwse-resize\\n|oblique|oldstyle-nums|open|open-quote|optimizeLegibility|optimizeQuality|optimizeSpeed|optional|ordinal|outset|outside|over|overlay|overline|padding\\n|padding-box|page|painted|pan-down|pan-left|pan-right|pan-up|pan-x|pan-y|paused|petite-caps|pixelated|plaintext|pointer|portrait|pre|pre-line\\n|pre-wrap|preserve-3d|progress|progressive|proportional-nums|proportional-width|proximity|radial|recto|region|relative|remove|repeat|repeat-[xy]\\n|reset-size|reverse|revert|ridge|right|rl|rl-tb|round|row|row-resize|row-reverse|row-severse|rtl|ruby|ruby-base|ruby-base-container|ruby-text\\n|ruby-text-container|run-in|running|s-resize|saturation|scale-down|screen|scroll|scroll-position|se-resize|semi-condensed|semi-expanded|separate\\n|sesame|show|sideways|sideways-left|sideways-lr|sideways-right|sideways-rl|simplified|slashed-zero|slice|small|small-caps|small-caption|smaller\\n|smooth|soft-light|solid|space|space-around|space-between|spell-out|square|sRGB|stacked-fractions|start|static|status-bar|swap|step-end|step-start\\n|sticky|stretch|strict|stroke|stroke-box|style|sub|subgrid|subpixel-antialiased|subtract|super|sw-resize|symbolic|table|table-caption|table-cell\\n|table-column|table-column-group|table-footer-group|table-header-group|table-row|table-row-group|tabular-nums|tb|tb-rl|text|text-after-edge\\n|text-before-edge|text-bottom|text-top|thick|thin|titling-caps|top|top-outside|touch|traditional|transparent|triangle|ultra-condensed|ultra-expanded\\n|under|underline|unicase|unset|upleft|uppercase|upright|use-glyph-orientation|use-script|verso|vertical|vertical-ideographic|vertical-lr|vertical-rl\\n|vertical-text|view-box|visible|visibleFill|visiblePainted|visibleStroke|w-resize|wait|wavy|weight|whitespace|wider|words|wrap|wrap-reverse\\n|x-large|x-small|xx-large|xx-small|zero|zoom-in|zoom-out)\\n(?![\\\\w-])\",\n                    \"name\": \"support.constant.property-value.css\"\n                },\n                {\n                    \"match\":\n                        \"(?xi) (?<![\\\\w-])\\n(arabic-indic|armenian|bengali|cambodian|circle|cjk-decimal|cjk-earthly-branch|cjk-heavenly-stem|cjk-ideographic\\n|decimal|decimal-leading-zero|devanagari|disc|disclosure-closed|disclosure-open|ethiopic-halehame-am\\n|ethiopic-halehame-ti-e[rt]|ethiopic-numeric|georgian|gujarati|gurmukhi|hangul|hangul-consonant|hebrew\\n|hiragana|hiragana-iroha|japanese-formal|japanese-informal|kannada|katakana|katakana-iroha|khmer\\n|korean-hangul-formal|korean-hanja-formal|korean-hanja-informal|lao|lower-alpha|lower-armenian|lower-greek\\n|lower-latin|lower-roman|malayalam|mongolian|myanmar|oriya|persian|simp-chinese-formal|simp-chinese-informal\\n|square|tamil|telugu|thai|tibetan|trad-chinese-formal|trad-chinese-informal|upper-alpha|upper-armenian\\n|upper-latin|upper-roman|urdu)\\n(?![\\\\w-])\",\n                    \"name\": \"support.constant.property-value.list-style-type.css\"\n                },\n                {\n                    \"match\":\n                        \"(?<![\\\\w-])(?i:-(?:ah|apple|atsc|epub|hp|khtml|moz|ms|o|rim|ro|tc|wap|webkit|xv)|(?:mso|prince))-[a-zA-Z-]+\",\n                    \"name\": \"support.constant.vendored.property-value.css\"\n                },\n                {\n                    \"match\":\n                        \"(?<![\\\\w-])(?i:arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace)(?![\\\\w-])\",\n                    \"name\": \"support.constant.font-name.css\"\n                }\n            ]\n        },\n        \"property-names\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?xi) (?<![\\\\w-])\\n(?:\\n    # Standard CSS\\n    additive-symbols|align-content|align-items|align-self|all|animation|animation-delay|animation-direction\\n  | animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state\\n  | animation-timing-function|backface-visibility|background|background-attachment|background-blend-mode\\n  | background-clip|background-color|background-image|background-origin|background-position|background-position-[xy]\\n  | background-repeat|background-size|block-size|border|border-block-end|border-block-end-color|border-block-end-style\\n  | border-block-end-width|border-block-start|border-block-start-color|border-block-start-style\\n  | border-block-start-width|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius\\n  | border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset\\n  | border-image-repeat|border-image-slice|border-image-source|border-image-width|border-inline-end\\n  | border-inline-end-color|border-inline-end-style|border-inline-end-width|border-inline-start\\n  | border-inline-start-color|border-inline-start-style|border-inline-start-width|border-left|border-left-color\\n  | border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style\\n  | border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius\\n  | border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-decoration-break\\n  | box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|clip-path|color\\n  | column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width\\n  | column-span|column-width|columns|content|counter-increment|counter-reset|cursor|direction|display\\n  | empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float\\n  | font|font-display|font-family|font-feature-settings|font-kerning|font-language-override|font-size|font-size-adjust\\n  | font-stretch|font-style|font-synthesis|font-variant|font-variant-alternates|font-variant-caps\\n  | font-variant-east-asian|font-variant-ligatures|font-variant-numeric|font-variant-position|font-weight\\n  | grid|grid-area|grid-auto-columns|grid-auto-flow|grid-auto-rows|grid-column|grid-column-end|grid-column-gap\\n  | grid-column-start|grid-gap|grid-row|grid-row-end|grid-row-gap|grid-row-start|grid-template|grid-template-areas\\n  | grid-template-columns|grid-template-rows|height|hyphens|image-orientation|image-rendering|image-resolution\\n  | ime-mode|inline-size|isolation|justify-content|left|letter-spacing|line-break|line-height|list-style\\n  | list-style-image|list-style-position|list-style-type|margin|margin-block-end|margin-block-start|margin-bottom\\n  | margin-inline-end|margin-inline-start|margin-left|margin-right|margin-top|mask|mask-clip|mask-composite\\n  | mask-image|mask-mode|mask-origin|mask-position|mask-repeat|mask-size|mask-type|max-block-size|max-height\\n  | max-inline-size|max-width|max-zoom|min-block-size|min-height|min-inline-size|min-width|min-zoom|mix-blend-mode\\n  | negative|object-fit|object-position|offset-block-end|offset-block-start|offset-inline-end|offset-inline-start\\n  | opacity|order|orientation|orphans|outline|outline-color|outline-offset|outline-style|outline-width|overflow\\n  | overflow-wrap|overflow-[xy]|pad|padding|padding-block-end|padding-block-start|padding-bottom|padding-inline-end\\n  | padding-inline-start|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside\\n  | perspective|perspective-origin|pointer-events|position|prefix|quotes|range|resize|right|ruby-align|ruby-merge\\n  | ruby-position|scroll-behavior|scroll-snap-coordinate|scroll-snap-destination|scroll-snap-type|shape-image-threshold\\n  | shape-margin|shape-outside|speak-as|src|suffix|symbols|system|tab-size|table-layout|text-align|text-align-last\\n  | text-combine-upright|text-decoration|text-decoration-color|text-decoration-line|text-decoration-style|text-emphasis\\n  | text-emphasis-color|text-emphasis-position|text-emphasis-style|text-indent|text-orientation|text-overflow\\n  | text-rendering|text-shadow|text-transform|text-underline-position|top|touch-action|transform|transform-box\\n  | transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property\\n  | transition-timing-function|unicode-bidi|unicode-range|user-zoom|vertical-align|visibility|white-space|widows\\n  | width|will-change|word-break|word-spacing|word-wrap|writing-mode|z-index|zoom\\n\\n  # SVG attributes\\n  | alignment-baseline|baseline-shift|clip-rule|color-interpolation|color-interpolation-filters|color-profile\\n  | color-rendering|dominant-baseline|enable-background|fill|fill-opacity|fill-rule|flood-color|flood-opacity\\n  | glyph-orientation-horizontal|glyph-orientation-vertical|kerning|lighting-color|marker-end|marker-mid\\n  | marker-start|shape-rendering|stop-color|stop-opacity|stroke|stroke-dasharray|stroke-dashoffset|stroke-linecap\\n  | stroke-linejoin|stroke-miterlimit|stroke-opacity|stroke-width|text-anchor|x|y\\n\\n  # Not listed on MDN; presumably deprecated\\n  | adjust|after|align|align-last|alignment|alignment-adjust|appearance|attachment|azimuth|background-break\\n  | balance|baseline|before|bidi|binding|bookmark|bookmark-label|bookmark-level|bookmark-target|border-length\\n  | bottom-color|bottom-left-radius|bottom-right-radius|bottom-style|bottom-width|box|box-align|box-direction\\n  | box-flex|box-flex-group|box-lines|box-ordinal-group|box-orient|box-pack|break|character|collapse|column\\n  | column-break-after|column-break-before|count|counter|crop|cue|cue-after|cue-before|decoration|decoration-break\\n  | delay|display-model|display-role|down|drop|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust\\n  | drop-initial-before-align|drop-initial-size|drop-initial-value|duration|elevation|emphasis|family|fit|fit-position\\n  | flex-group|float-offset|gap|grid-columns|grid-rows|hanging-punctuation|header|hyphenate|hyphenate-after|hyphenate-before\\n  | hyphenate-character|hyphenate-lines|hyphenate-resource|icon|image|increment|indent|index|initial-after-adjust\\n  | initial-after-align|initial-before-adjust|initial-before-align|initial-size|initial-value|inline-box-align|iteration-count\\n  | justify|label|left-color|left-style|left-width|length|level|line|line-stacking|line-stacking-ruby|line-stacking-shift\\n  | line-stacking-strategy|lines|list|mark|mark-after|mark-before|marks|marquee|marquee-direction|marquee-play-count|marquee-speed\\n  | marquee-style|max|min|model|move-to|name|nav|nav-down|nav-index|nav-left|nav-right|nav-up|new|numeral|offset|ordinal-group\\n  | orient|origin|overflow-style|overhang|pack|page|page-policy|pause|pause-after|pause-before|phonemes|pitch|pitch-range\\n  | play-count|play-during|play-state|point|presentation|presentation-level|profile|property|punctuation|punctuation-trim\\n  | radius|rate|rendering-intent|repeat|replace|reset|resolution|resource|respond-to|rest|rest-after|rest-before|richness\\n  | right-color|right-style|right-width|role|rotation|rotation-point|rows|ruby|ruby-overhang|ruby-span|rule|rule-color\\n  | rule-style|rule-width|shadow|size|size-adjust|sizing|space|space-collapse|spacing|span|speak|speak-header|speak-numeral\\n  | speak-punctuation|speech|speech-rate|speed|stacking|stacking-ruby|stacking-shift|stacking-strategy|stress|stretch\\n  | string-set|style|style-image|style-position|style-type|target|target-name|target-new|target-position|text|text-height\\n  | text-justify|text-outline|text-replace|text-wrap|timing-function|top-color|top-left-radius|top-right-radius|top-style\\n  | top-width|trim|unicode|up|user-select|variant|voice|voice-balance|voice-duration|voice-family|voice-pitch|voice-pitch-range\\n  | voice-rate|voice-stress|voice-volume|volume|weight|white|white-space-collapse|word|wrap\\n)\\n(?![\\\\w-])\",\n                    \"name\": \"support.type.property-name.css\"\n                },\n                {\n                    \"match\":\n                        \"(?<![\\\\w-])(?i:-(?:ah|apple|atsc|epub|hp|khtml|moz|ms|o|rim|ro|tc|wap|webkit|xv)|(?:mso|prince))-[a-zA-Z-]+\",\n                    \"name\": \"support.type.vendored.property-name.css\"\n                }\n            ]\n        },\n        \"property-values\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#commas\"\n                },\n                {\n                    \"include\": \"#comment-block\"\n                },\n                {\n                    \"include\": \"#escapes\"\n                },\n                {\n                    \"include\": \"#functions\"\n                },\n                {\n                    \"include\": \"#property-keywords\"\n                },\n                {\n                    \"include\": \"#unicode-range\"\n                },\n                {\n                    \"include\": \"#numeric-values\"\n                },\n                {\n                    \"include\": \"#color-keywords\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"match\": \"!\\\\s*important(?![\\\\w-])\",\n                    \"name\": \"keyword.other.important.css\"\n                }\n            ]\n        },\n        \"pseudo-classes\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.colon.css\"\n                }\n            },\n            \"match\":\n                \"(?xi)\\n(:)(:*)\\n(?: active|any-link|checked|default|disabled|empty|enabled|first\\n  | (?:first|last|only)-(?:child|of-type)|focus|focus-within|fullscreen|host|hover\\n  | in-range|indeterminate|invalid|left|link|optional|out-of-range\\n  | read-only|read-write|required|right|root|scope|target|unresolved\\n  | valid|visited\\n)(?![\\\\w-]|\\\\s*[;}])\",\n            \"name\": \"entity.other.attribute-name.pseudo-class.css\"\n        },\n        \"pseudo-elements\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                }\n            },\n            \"match\":\n                \"(?xi)\\n(?:\\n  (::?)                       # Elements using both : and :: notation\\n  (?: after\\n    | before\\n    | first-letter\\n    | first-line\\n    | (?:-(?:ah|apple|atsc|epub|hp|khtml|moz\\n            |ms|o|rim|ro|tc|wap|webkit|xv)\\n        | (?:mso|prince))\\n      -[a-z-]+\\n  )\\n  |\\n  (::)                        # Double-colon only\\n  (?: backdrop\\n    | content\\n    | grammar-error\\n    | marker\\n    | placeholder\\n    | selection\\n    | shadow\\n    | spelling-error\\n  )\\n)\\n(?![\\\\w-]|\\\\s*[;}])\",\n            \"name\": \"entity.other.attribute-name.pseudo-element.css\"\n        },\n        \"rule-list\": {\n            \"begin\": \"{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.property-list.begin.bracket.curly.css\"\n                }\n            },\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.property-list.end.bracket.curly.css\"\n                }\n            },\n            \"name\": \"meta.property-list.css\",\n            \"patterns\": [\n                {\n                    \"include\": \"#rule-list-innards\"\n                }\n            ]\n        },\n        \"rule-list-innards\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment-block\"\n                },\n                {\n                    \"include\": \"#escapes\"\n                },\n                {\n                    \"include\": \"#font-features\"\n                },\n                {\n                    \"match\":\n                        \"(?x) (?<![\\\\w-])\\n--\\n(?:[-a-zA-Z_]    | [^\\\\x00-\\\\x7F])     # First letter\\n(?:[-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]      # Remainder of identifier\\n  |\\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n)*\",\n                    \"name\": \"variable.css\"\n                },\n                {\n                    \"begin\": \"(?<![-a-zA-Z])(?=[-a-zA-Z])\",\n                    \"end\": \"$|(?![-a-zA-Z])\",\n                    \"name\": \"meta.property-name.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#property-names\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(:)\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.key-value.css\"\n                        }\n                    },\n                    \"end\": \"\\\\s*(;)|\\\\s*(?=}|\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.terminator.rule.css\"\n                        }\n                    },\n                    \"contentName\": \"meta.property-value.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#property-values\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \";\",\n                    \"name\": \"punctuation.terminator.rule.css\"\n                }\n            ]\n        },\n        \"selector\": {\n            \"begin\":\n                \"(?x)\\n(?=\\n  (?:\\\\|)?                    # Possible anonymous namespace prefix\\n  (?:\\n    [-\\\\[:.*\\\\#a-zA-Z_]       # Valid selector character\\n    |\\n    [^\\\\x00-\\\\x7F]            # Which can include non-ASCII symbols\\n    |\\n    \\\\\\\\                      # Or an escape sequence\\n    (?:[0-9a-fA-F]{1,6}|.)\\n  )\\n)\",\n            \"end\": \"(?=\\\\s*[/@{)])\",\n            \"name\": \"meta.selector.css\",\n            \"patterns\": [\n                {\n                    \"include\": \"#selector-innards\"\n                }\n            ]\n        },\n        \"selector-innards\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment-block\"\n                },\n                {\n                    \"include\": \"#commas\"\n                },\n                {\n                    \"include\": \"#escapes\"\n                },\n                {\n                    \"include\": \"#combinators\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.namespace-prefix.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.css\"\n                        }\n                    },\n                    \"match\":\n                        \"(?x)\\n(?:^|(?<=[\\\\s,(};]))         # Follows whitespace, comma, semicolon, or bracket\\n(?!\\n  [-\\\\w*]+\\n  \\\\|\\n  (?!\\n      [-\\\\[:.*\\\\#a-zA-Z_]    # Make sure there's a selector to match\\n    | [^\\\\x00-\\\\x7F]\\n  )\\n)\\n(\\n  (?: [-a-zA-Z_]    | [^\\\\x00-\\\\x7F] )   # First letter\\n  (?: [-a-zA-Z0-9_] | [^\\\\x00-\\\\x7F]     # Remainder of identifier\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)\\n  )*\\n  |\\n  \\\\*     # Universal namespace\\n)?\\n(\\\\|)     # Namespace separator\"\n                },\n                {\n                    \"include\": \"#tag-names\"\n                },\n                {\n                    \"match\": \"\\\\*\",\n                    \"name\": \"entity.name.tag.wildcard.css\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        }\n                    },\n                    \"match\":\n                        \"(?x) (?<![@\\\\w-])\\n([.\\\\#])\\n# Invalid identifier\\n(\\n  (?:\\n    # Starts with ASCII digits, with possible hyphen preceding it\\n    -?[0-9]\\n    |\\n    # Consists of a hyphen only\\n    -                                      # Terminated by either:\\n    (?= $                                  # - End-of-line\\n      | [\\\\s,.\\\\#)\\\\[:{>+~|]               # - Followed by another selector\\n      | /\\\\*                               # - Followed by a block comment\\n    )\\n    |\\n    # Name contains unescaped ASCII symbol\\n    (?:                                    # Check for acceptable preceding characters\\n        [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]       # - Valid selector character\\n      | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)         # - Escape sequence\\n    )*\\n    (?:                                    # Invalid punctuation\\n      [!\\\"'%&(*;<?@^`|\\\\]}]                 # - NOTE: We exempt `)` from the list of checked\\n      |                                    #   symbols to avoid matching `:not(.invalid)`\\n      / (?!\\\\*)                            # - Avoid invalidating the start of a comment\\n    )+\\n  )\\n  # Mark remainder of selector invalid\\n  (?: [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]         # - Otherwise valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)           # - Escape sequence\\n  )*\\n)\",\n                    \"name\": \"invalid.illegal.bad-identifier.css\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        }\n                    },\n                    \"match\":\n                        \"(?x)\\n(\\\\.)                                  # Valid class-name\\n(\\n  (?: [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]     # Valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n  )+\\n)                                      # Followed by either:\\n(?= $                                  # - End of the line\\n  | [\\\\s,.\\\\#)\\\\[:{>+~|]               # - Another selector\\n  | /\\\\*                               # - A block comment\\n)\",\n                    \"name\": \"entity.other.attribute-name.class.css\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        }\n                    },\n                    \"match\":\n                        \"(?x)\\n(\\\\#)\\n(\\n  -?\\n  (?![0-9])\\n  (?:[-a-zA-Z0-9_]|[^\\\\x00-\\\\x7F]|\\\\\\\\(?:[0-9a-fA-F]{1,6}|.))+\\n)\\n(?=$|[\\\\s,.\\\\#)\\\\[:{>+~|]|/\\\\*)\",\n                    \"name\": \"entity.other.attribute-name.id.css\"\n                },\n                {\n                    \"begin\": \"\\\\[\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.entity.begin.bracket.square.css\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.entity.end.bracket.square.css\"\n                        }\n                    },\n                    \"name\": \"meta.attribute-selector.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment-block\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"storage.modifier.ignore-case.css\"\n                                }\n                            },\n                            \"match\": \"(?<=[\\\"'\\\\s]|^|\\\\*/)\\\\s*([iI])\\\\s*(?=[\\\\s\\\\]]|/\\\\*|$)\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"string.unquoted.attribute-value.css\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escapes\"\n                                        }\n                                    ]\n                                }\n                            },\n                            \"match\": \"(?x)(?<==)\\\\s*((?!/\\\\*)(?:[^\\\\\\\\\\\"'\\\\s\\\\]]|\\\\\\\\.)+)\"\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        },\n                        {\n                            \"match\": \"[~|^$*]?=\",\n                            \"name\": \"keyword.operator.pattern.css\"\n                        },\n                        {\n                            \"match\": \"\\\\|\",\n                            \"name\": \"punctuation.separator.css\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"entity.other.namespace-prefix.css\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escapes\"\n                                        }\n                                    ]\n                                }\n                            },\n                            \"match\":\n                                \"(?x)\\n# Qualified namespace prefix\\n( -?(?!\\\\d)(?:[\\\\w-]|[^\\\\x00-\\\\x7F]|\\\\\\\\(?:[0-9a-fA-F]{1,6}|.))+\\n| \\\\*\\n)\\n# Lookahead to ensure there's a valid identifier ahead\\n(?=\\n  \\\\| (?!\\\\s|=|$|\\\\])\\n  (?: -?(?!\\\\d)\\n   |   [\\\\\\\\\\\\w-]\\n   |   [^\\\\x00-\\\\x7F]\\n   )\\n)\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"entity.other.attribute-name.css\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escapes\"\n                                        }\n                                    ]\n                                }\n                            },\n                            \"match\":\n                                \"(?x)\\n(-?(?!\\\\d)(?>[\\\\w-]|[^\\\\x00-\\\\x7F]|\\\\\\\\(?:[0-9a-fA-F]{1,6}|.))+)\\n\\\\s*\\n(?=[~|^\\\\]$*=]|/\\\\*)\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#pseudo-classes\"\n                },\n                {\n                    \"include\": \"#pseudo-elements\"\n                },\n                {\n                    \"include\": \"#functional-pseudo-classes\"\n                },\n                {\n                    \"match\":\n                        \"(?x) (?<![@\\\\w-])\\n(?=            # Custom element names must:\\n  [a-z]        # - start with a lowercase ASCII letter,\\n  \\\\w* -       # - contain at least one dash\\n)\\n(?:\\n  (?![A-Z])    # No uppercase ASCII letters are allowed\\n  [\\\\w-]       # Allow any other word character or dash\\n)+\\n(?![(\\\\w-])\",\n                    \"name\": \"entity.name.tag.custom.css\"\n                }\n            ]\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\"\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.css\"\n                        }\n                    },\n                    \"end\": \"\\\"|(?<!\\\\\\\\)(?=$|\\\\n)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.css\"\n                        }\n                    },\n                    \"name\": \"string.quoted.double.css\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?:\\\\G|^)(?=(?:[^\\\\\\\\\\\"]|\\\\\\\\.)+$)\",\n                            \"end\": \"$\",\n                            \"name\": \"invalid.illegal.unclosed.string.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.css\"\n                        }\n                    },\n                    \"end\": \"'|(?<!\\\\\\\\)(?=$|\\\\n)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.css\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.css\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?:\\\\G|^)(?=(?:[^\\\\\\\\']|\\\\\\\\.)+$)\",\n                            \"end\": \"$\",\n                            \"name\": \"invalid.illegal.unclosed.string.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escapes\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#escapes\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"tag-names\": {\n            \"match\":\n                \"(?xi) (?<![\\\\w:-])\\n(?:\\n    # HTML\\n    a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|bgsound\\n  | big|blink|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command\\n  | content|data|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|element|em|embed|fieldset\\n  | figcaption|figure|font|footer|form|frame|frameset|h[1-6]|head|header|hgroup|hr|html|i\\n  | iframe|image|img|input|ins|isindex|kbd|keygen|label|legend|li|link|listing|main|map|mark\\n  | marquee|math|menu|menuitem|meta|meter|multicol|nav|nextid|nobr|noembed|noframes|noscript\\n  | object|ol|optgroup|option|output|p|param|picture|plaintext|pre|progress|q|rb|rp|rt|rtc\\n  | ruby|s|samp|script|section|select|shadow|slot|small|source|spacer|span|strike|strong\\n  | style|sub|summary|sup|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr\\n  | track|tt|u|ul|var|video|wbr|xmp\\n\\n  # SVG\\n  | altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform\\n  | circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix\\n  | feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap\\n  | feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur\\n  | feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting\\n  | feSpotLight|feTile|feTurbulence|filter|font-face|font-face-format|font-face-name\\n  | font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern\\n  | line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata\\n  | missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor\\n  | stop|svg|switch|symbol|text|textPath|tref|tspan|use|view|vkern\\n\\n  # MathML\\n  | annotation|annotation-xml|maction|maligngroup|malignmark|math|menclose|merror|mfenced\\n  | mfrac|mglyph|mi|mlabeledtr|mlongdiv|mmultiscripts|mn|mo|mover|mpadded|mphantom|mroot\\n  | mrow|ms|mscarries|mscarry|msgroup|msline|mspace|msqrt|msrow|mstack|mstyle|msub|msubsup\\n  | msup|mtable|mtd|mtext|mtr|munder|munderover|semantics\\n)\\n(?=[+~>\\\\s,.\\\\#|){:\\\\[]|/\\\\*|$)\",\n            \"name\": \"entity.name.tag.css\"\n        },\n        \"unicode-range\": {\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"constant.other.unicode-range.css\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.separator.dash.unicode-range.css\"\n                }\n            },\n            \"match\": \"(?<![\\\\w-])[Uu]\\\\+[0-9A-Fa-f?]{1,6}(?:(-)[0-9A-Fa-f]{1,6})?(?![\\\\w-])\"\n        },\n        \"url\": {\n            \"begin\": \"(?i)(?<![\\\\w@-])(url)(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"support.function.url.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.function.begin.bracket.round.css\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.function.end.bracket.round.css\"\n                }\n            },\n            \"name\": \"meta.function.url.css\",\n            \"patterns\": [\n                {\n                    \"match\": \"[^'\\\")\\\\s]+\",\n                    \"name\": \"variable.parameter.url.css\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment-block\"\n                },\n                {\n                    \"include\": \"#escapes\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/elixir/syntaxes/eex.tmLanguage.json",
    "content": "{\n    \"fileTypes\": [\"eex\"],\n    \"name\": \"EEx\",\n    \"patterns\": [\n        {\n            \"begin\": \"<%+#\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.eex\"\n                }\n            },\n            \"end\": \"%>\",\n            \"name\": \"comment.block.eex\"\n        },\n        {\n            \"begin\": \"<%+(?!>)[-=]*\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.elixir\"\n                }\n            },\n            \"end\": \"-?%>\",\n            \"name\": \"source.elixir.embedded\",\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.elixir\"\n                        }\n                    },\n                    \"match\": \"(#).*?(?=-?%>)\",\n                    \"name\": \"comment.line.number-sign.elixir\"\n                },\n                {\n                    \"include\": \"source.elixir\"\n                }\n            ]\n        }\n    ],\n    \"scopeName\": \"text.elixir\"\n}\n"
  },
  {
    "path": "extensions/elixir/syntaxes/elixir.tmLanguage.json",
    "content": "﻿{\n    \"comment\": \"Oni Syntax Parser for Elixir Programming Language.\",\n    \"fileTypes\": [\"ex\", \"exs\"],\n    \"firstLineMatch\": \"^#!/.*\\\\belixir\",\n    \"foldingStartMarker\": \"(after|else|catch|rescue|\\\\-\\\\>|\\\\{|\\\\[|do)\\\\s*$\",\n    \"foldingStopMarker\": \"^\\\\s*((\\\\}|\\\\]|after|else|catch|rescue)\\\\s*$|end\\\\b)\",\n    \"name\": \"Elixir\",\n    \"patterns\": [\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.module.elixir\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.module.elixir\"\n                }\n            },\n            \"match\": \"^\\\\s*(defmodule)\\\\s+(([A-Z]\\\\w*\\\\s*(\\\\.)\\\\s*)*[A-Z]\\\\w*)\",\n            \"name\": \"meta.module.elixir\"\n        },\n        {\n            \"begin\": \"@(module|type)?doc (~s)?\\\"\\\"\\\"\",\n            \"comment\": \"@doc with interpolated heredocs\",\n            \"end\": \"\\\\s*\\\"\\\"\\\"\",\n            \"name\": \"comment.documentation.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"@(module|type)?doc ~s'''\",\n            \"comment\": \"@doc with interpolated single quoted heredocs\",\n            \"end\": \"\\\\s*'''\",\n            \"name\": \"comment.documentation.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"@(module|type)?doc ~S\\\"\\\"\\\"\",\n            \"comment\": \"@doc with heredocs is treated as documentation\",\n            \"end\": \"\\\\s*\\\"\\\"\\\"\",\n            \"name\": \"comment.documentation.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"@(module|type)?doc ~S'''\",\n            \"comment\": \"@doc with heredocs is treated as documentation\",\n            \"end\": \"\\\\s*'''\",\n            \"name\": \"comment.documentation.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"@doc false is treated as documentation\",\n            \"match\": \"@(module|type)?doc false\",\n            \"name\": \"comment.documentation.false\"\n        },\n        {\n            \"begin\": \"@(module|type)?doc \\\"\",\n            \"comment\": \"@doc with string is treated as documentation\",\n            \"end\": \"\\\"\",\n            \"name\": \"comment.documentation.string\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"match\": \"(?<!\\\\.)\\\\b(alias|require|import|use)\\\\b(?![?!])\",\n            \"name\": \"keyword.other.special-method.elixir\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                }\n            },\n            \"comment\": \"symbols\",\n            \"match\": \"(?>[a-zA-Z_][\\\\w@]*(?>[?!])?)(:)(?!:)\",\n            \"name\": \"constant.other.symbol.elixir\"\n        },\n        {\n            \"match\":\n                \"(?<!\\\\.)\\\\b(do|end|case|bc|lc|for|if|cond|with|unless|try|receive|fn|defmodule|defprotocol|defimpl|defrecordp?|defstruct|defdelegate|defcallback|defexception|defoverridable|defguardp?|exit|after|rescue|catch|else|raise|throw|quote|unquote|super|when|and|or|not|in)\\\\b(?![?!])\",\n            \"name\": \"keyword.control.elixir\"\n        },\n        {\n            \"comment\": \"Function with parameters\",\n            \"begin\": \"\\\\b(defp?|defmacrop?)\\\\b\\\\s*([_$a-z][$\\\\w]*[!?]?)\\\\s*\\\\(\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.elixir\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.elixir\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                },\n                {\n                    \"include\": \"#function_parameter\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Function without parameters\",\n            \"match\": \"\\\\b(defp?|defmacrop?)\\\\b\\\\s*([_$a-z][$\\\\w]*[!?]?)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.elixir\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.elixir\"\n                }\n            }\n        },\n        {\n            \"comment\": \" as above, just doesn't need a 'end' and does a logic operation\",\n            \"match\": \"(?<!\\\\.)\\\\b(and|not|or|when|xor|in|inlist|inbits)\\\\b\",\n            \"name\": \"keyword.operator.elixir\"\n        },\n        {\n            \"match\": \"\\\\b(nil|true|false)\\\\b(?![?!])\",\n            \"name\": \"constant.language.elixir\"\n        },\n        {\n            \"match\": \"\\\\b(__(CALLER|ENV|MODULE|DIR)__)\\\\b(?![?!])\",\n            \"name\": \"variable.language.elixir\"\n        },\n        {\n            \"match\": \"\\\\b[A-Z]\\\\w*\\\\b\",\n            \"name\": \"variable.other.constant.elixir\"\n        },\n        {\n            \"match\":\n                \"\\\\b(0[xX]\\\\h(?>_?\\\\h)*|\\\\d(?>_?\\\\d)*(\\\\.(?![^[:space:][:digit:]])(?>_?\\\\d)*)?([eE][-+]?\\\\d(?>_?\\\\d)*)?|0[bB][01]+)\\\\b\",\n            \"name\": \"constant.numeric.elixir\"\n        },\n        {\n            \"comment\": \"Regex sigil with curlies\",\n            \"begin\": \"~r\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\}[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_curly\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with pipes\",\n            \"begin\": \"~r\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\|[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with parens\",\n            \"begin\": \"~r\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\)[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with slashes\",\n            \"begin\": \"~r\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\/[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with brackets\",\n            \"begin\": \"~r\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\][eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with ltgt\",\n            \"begin\": \"~r\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\>[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with single quoted heredocs\",\n            \"begin\": \"~r\\\\'\\\\'\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'\\\\'\\\\'[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with single quotes\",\n            \"begin\": \"~r\\\\\\\"\\\\\\\"\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"\\\\\\\"\\\\\\\"[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with double quotes\",\n            \"begin\": \"~r\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Regex sigil with single quotes\",\n            \"begin\": \"~r\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with curlies\",\n            \"begin\": \"~R\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\}[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_curly\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with pipes\",\n            \"begin\": \"~R\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\|[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\"\n        },\n        {\n            \"comment\": \"Literal regex sigil with parens\",\n            \"begin\": \"~R\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\)[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_parens\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with slashes\",\n            \"begin\": \"~R\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\/[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\"\n        },\n        {\n            \"comment\": \"Literal regex sigil with brackets\",\n            \"begin\": \"~R\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\][eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with ltgt\",\n            \"begin\": \"~R\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\>[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with single quoted heredoc\",\n            \"begin\": \"~R\\\\'\\\\'\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'\\\\'\\\\'[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with double quoted heredoc\",\n            \"begin\": \"~R\\\\\\\"\\\\\\\"\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"\\\\\\\"\\\\\\\"[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with double quotes\",\n            \"begin\": \"~R\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal regex sigil with single quotes\",\n            \"begin\": \"~R\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'[eimnosux]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.regexp.end.elixir\"\n                }\n            },\n            \"name\": \"string.regexp.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with curlies\",\n            \"begin\": \"~c\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\}[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with pipes\",\n            \"begin\": \"~c\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\|[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with parens\",\n            \"begin\": \"~c\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\)[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with curlies\",\n            \"begin\": \"~c\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\>[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with curlies\",\n            \"begin\": \"~c\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\][a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with curlies\",\n            \"begin\": \"~c\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\/[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with single quoted heredoc\",\n            \"begin\": \"~c\\\\'\\\\'\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'\\\\'\\\\'[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with double quoted heredoc\",\n            \"begin\": \"~c\\\\\\\"\\\\\\\"\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"\\\\\\\"\\\\\\\"[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with curlies\",\n            \"begin\": \"~c\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Character list sigil with curlies\",\n            \"begin\": \"~c\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Literal Character list sigil with curlies\",\n            \"begin\": \"~C\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\}[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with pipes\",\n            \"begin\": \"~C\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\|[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with parens\",\n            \"begin\": \"~C\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\)[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with curlies\",\n            \"begin\": \"~C\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\>[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with curlies\",\n            \"begin\": \"~C\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\][a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with curlies\",\n            \"begin\": \"~C\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\/[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with single quoted heredoc\",\n            \"begin\": \"~C\\\\'\\\\'\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'\\\\'\\\\'[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with double quoted heredoc\",\n            \"begin\": \"~C\\\\\\\"\\\\\\\"\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"\\\\\\\"\\\\\\\"[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with curlies\",\n            \"begin\": \"~C\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"comment\": \"Literal Character list sigil with curlies\",\n            \"begin\": \"~C\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\"\n        },\n        {\n            \"begin\": \"~w\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\}[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_curly\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\][acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\>[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\)[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_parens\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\/[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\|[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Interpolated word list sigil with single quoted heredoc\",\n            \"begin\": \"~w\\\\'\\\\'\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'\\\\'\\\\'[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Interpolated word list sigil with double quoted heredoc\",\n            \"begin\": \"~w\\\\\\\"\\\\\\\"\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"\\\\\\\"\\\\\\\"[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\'[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~w\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\\\\"[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~W\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\}[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~W\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\][acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~W\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\>[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~W\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\)[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_parens\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~W\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\/[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~W\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\|[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"comment\": \"Literal word list sigil with single quoted heredoc\",\n            \"begin\": \"~W\\\\'\\\\'\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\'\\\\'\\\\'[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"comment\": \"Literal word list sigil with double quoted heredoc\",\n            \"begin\": \"~W\\\\\\\"\\\\\\\"\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"end\": \"\\\\\\\"\\\\\\\"\\\\\\\"[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~W\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\'[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~W\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\\\\"[acs]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.list.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[a-z](?>\\\"\\\"\\\")\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"Double-quoted heredocs sigils\",\n            \"end\": \"^\\\\s*\\\"\\\"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z](?>''')\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"Double-quoted heredocs sigils\",\n            \"end\": \"^\\\\s*'''\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\}[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_curly\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\][a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\>[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\)[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"include\": \"#nest_parens\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\/[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\'[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\\\\"[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[a-z]\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (allow for interpolation)\",\n            \"end\": \"\\\\|[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.interpolated.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[A-Z](?>\\\"\\\"\\\")\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"Double-quoted heredocs sigils\",\n            \"end\": \"^\\\\s*\\\"\\\"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.other.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[A-Z](?>''')\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"Double-quoted heredocs sigils\",\n            \"end\": \"^\\\\s*'''\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.other.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\}[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\][a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\>[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\)[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_parens\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\/\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\/[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\'[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\\\\"[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \"~[A-Z]\\\\|\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"sigil (without interpolation)\",\n            \"end\": \"\\\\|[a-z]*\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.literal.elixir\"\n        },\n        {\n            \"begin\": \":'\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                }\n            },\n            \"end\": \"'\",\n            \"name\": \"constant.other.symbol.single-quoted.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"symbols with single-quoted string, used as keys in Keyword lists.\",\n            \"match\": \"(')((?:[^'\\\\\\\\]*(?:\\\\\\\\.[^'\\\\\\\\]*)*))(':)(?!:)\",\n            \"name\": \"constant.other.symbol.single-quoted.elixir\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolated_elixir\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                }\n            }\n        },\n        {\n            \"begin\": \":\\\"\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"name\": \"constant.other.symbol.double-quoted.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?>''')\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"Single-quoted heredocs\",\n            \"end\": \"^\\\\s*'''\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"single quoted string (allows for interpolation)\",\n            \"end\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"support.function.variable.quoted.single.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?>\\\"\\\"\\\")\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"Double-quoted heredocs\",\n            \"end\": \"^\\\\s*\\\"\\\"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.heredoc.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"symbols defined by double-quoted string, used as keys in Keyword lists.\",\n            \"match\": \"(\\\")((?:[^\\\"\\\\\\\\]*(?:\\\\\\\\.[^\\\"\\\\\\\\]*)*))(\\\":)(?!:)\",\n            \"name\": \"constant.other.symbol.double-quoted.elixir\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolated_elixir\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                }\n            }\n        },\n        {\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.elixir\"\n                }\n            },\n            \"comment\": \"double quoted string (allows for interpolation)\",\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.elixir\"\n                }\n            },\n            \"name\": \"string.quoted.double.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"#\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.elixir\"\n                }\n            },\n            \"end\": \"\\\\n\",\n            \"name\": \"comment.line.number-sign.elixir\"\n        },\n        {\n            \"match\": \"\\\\b_([\\\\w]+[?!]?)\",\n            \"name\": \"comment.unused.elixir\"\n        },\n        {\n            \"match\": \"\\\\b_\\\\b\",\n            \"name\": \"comment.wildcard.elixir\"\n        },\n        {\n            \"comment\":\n                \"matches questionmark-letters.\\n\\nexamples (1st alternation = hex):\\n?\\\\x1     ?\\\\x61\\n\\nexamples (2nd alternation = octal):\\n?\\\\0      ?\\\\07     ?\\\\017\\n\\nexamples (3rd alternation = escaped):\\n?\\\\n      ?\\\\b\\n\\nexamples (4th alternation = meta-ctrl):\\n?\\\\C-a    ?\\\\M-a    ?\\\\C-\\\\M-\\\\C-\\\\M-a\\n\\nexamples (4th alternation = normal):\\n?a       ?A       ?0\\n?*       ?\\\"       ?(\\n?.       ?#\\n\\n\\nthe negative lookbehind prevents against matching\\np(42.tainted?)\",\n            \"match\":\n                \"(?<!\\\\w)\\\\?(\\\\\\\\(x\\\\h{1,2}(?!\\\\h)\\\\b|0[0-7]{0,2}(?![0-7])\\\\b|[^x0MC])|(\\\\\\\\[MC]-)+\\\\w|[^\\\\s\\\\\\\\])\",\n            \"name\": \"constant.numeric.elixir\"\n        },\n        {\n            \"match\": \"(\\\\|\\\\|\\\\||&&&|\\\\^\\\\^\\\\^|<<<|>>>|~~~)\",\n            \"name\": \"keyword.operator.bitwise.elixir\"\n        },\n        {\n            \"comment\": \"matches: | ++ -- ** \\\\ <- <> << >> :: .. |> => -> <|> <~> <~ <<~ ~> ~>>\",\n            \"match\":\n                \"\\\\+\\\\+|\\\\-\\\\-|\\\\*\\\\*|\\\\\\\\\\\\\\\\|\\\\<\\\\-|<\\\\<\\\\~|\\\\<\\\\>|\\\\<\\\\<|\\\\>\\\\>|\\\\:\\\\:|\\\\.\\\\.|\\\\|>|=>|<\\\\|\\\\>|<~>|->|~>>|~>|<~|(?<!\\\\|)\\\\|(?!\\\\|)\",\n            \"name\": \"keyword.operator.other.elixir\"\n        },\n        {\n            \"match\": \"===?|!==?|<=?|>=?|=~\",\n            \"name\": \"keyword.operator.comparison.elixir\"\n        },\n        {\n            \"match\": \"(?<=[ \\\\t])!+|\\\\bnot\\\\b|&&|\\\\band\\\\b|\\\\|\\\\||\\\\bor\\\\b|\\\\bxor\\\\b\",\n            \"name\": \"keyword.operator.logical.elixir\"\n        },\n        {\n            \"match\": \"(\\\\*|\\\\+|\\\\-|/)\",\n            \"name\": \"keyword.operator.arithmetic.elixir\"\n        },\n        {\n            \"match\": \"=\",\n            \"name\": \"keyword.operator.assignment.elixir\"\n        },\n        {\n            \"match\": \"\\\\;\",\n            \"name\": \"punctuation.separator.statement.elixir\"\n        },\n        {\n            \"match\": \",\",\n            \"name\": \"punctuation.separator.object.elixir\"\n        },\n        {\n            \"match\": \"\\\\.\",\n            \"name\": \"punctuation.separator.method.elixir\"\n        },\n        {\n            \"match\": \"\\\\{|\\\\}\",\n            \"name\": \"punctuation.section.scope.elixir\"\n        },\n        {\n            \"match\": \"\\\\[\\\\]|\\\\[|\\\\]\",\n            \"name\": \"punctuation.section.array.elixir\"\n        },\n        {\n            \"match\": \"\\\\(|\\\\)\",\n            \"name\": \"punctuation.section.function.elixir\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.elixir\"\n                }\n            },\n            \"match\": \"(@)[a-zA-Z_]\\\\w*\",\n            \"name\": \"variable.other.readwrite.module.elixir\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.elixir\"\n                }\n            },\n            \"match\": \"(&)\\\\d*\",\n            \"name\": \"variable.other.anonymous.elixir\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.elixir\"\n                }\n            },\n            \"comment\": \"symbols\",\n            \"match\":\n                \"(?<!:)(:)(?>[a-zA-Z_][\\\\w@]*(?>[?!]|=(?![>=]))?|\\\\<\\\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\\\-|\\\\|>|=>|~|~=|=|/|\\\\\\\\\\\\\\\\|\\\\*\\\\*?|\\\\.\\\\.?\\\\.?|>=?|<=?|&&?&?|\\\\+\\\\+?|\\\\-\\\\-?|\\\\|\\\\|?\\\\|?|\\\\!|@|\\\\%?\\\\{\\\\}|%|\\\\[\\\\]|\\\\^(\\\\^\\\\^)?)\",\n            \"name\": \"constant.other.symbol.elixir\"\n        },\n        {\n            \"match\": \":\",\n            \"name\": \"punctuation.separator.other.elixir\"\n        }\n    ],\n    \"repository\": {\n        \"escaped_char\": {\n            \"match\": \"\\\\\\\\(?:[0-7]{1,3}|x[\\\\da-fA-F]{1,2}|.)\",\n            \"name\": \"constant.character.escape.elixir\"\n        },\n        \"function_parameter\": {\n            \"match\": \"[_$a-z][$\\\\w]*[?!]?\",\n            \"name\": \"parameter.variable.function.elixir\"\n        },\n        \"interpolated_elixir\": {\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.elixir\"\n                        },\n                        \"1\": {\n                            \"name\": \"source.elixir.embedded.source.empty\"\n                        }\n                    },\n                    \"match\": \"#\\\\{(\\\\})\",\n                    \"name\": \"source.elixir.embedded.source\"\n                },\n                {\n                    \"begin\": \"#\\\\{\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.elixir\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"name\": \"source.elixir.embedded.source\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#nest_curly_and_self\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"nest_brackets\": {\n            \"begin\": \"\\\\[\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.scope.elixir\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_brackets\"\n                }\n            ]\n        },\n        \"nest_curly\": {\n            \"begin\": \"\\\\{\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.scope.elixir\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_curly\"\n                }\n            ]\n        },\n        \"nest_curly_and_self\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\{\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.scope.elixir\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#nest_curly_and_self\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"nest_ltgt\": {\n            \"begin\": \"\\\\<\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.scope.elixir\"\n                }\n            },\n            \"end\": \"\\\\>\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_ltgt\"\n                }\n            ]\n        },\n        \"nest_parens\": {\n            \"begin\": \"\\\\(\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.scope.elixir\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#nest_parens\"\n                }\n            ]\n        },\n        \"regex_sub\": {\n            \"name\": \"string.interpolated.regexp.elixir\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_elixir\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"name\": \"string.regexp.arbitrary-repitition.elixir\",\n                    \"match\": \"(\\\\{)\\\\d+(,\\\\d+)?(\\\\})\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.arbitrary-repitition.elixir\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arbitrary-repitition.elixir\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"string.regexp.character-class.elixir\",\n                    \"begin\": \"\\\\[(?:\\\\^?\\\\])?\",\n                    \"end\": \"\\\\]\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.character-class.elixir\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.elixir\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"name\": \"string.regexp.group.elixir\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regex_sub\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|\\\\s)(#)\\\\s(?=[[a-zA-Z0-9,. \\\\t?!-][^\\\\x{00}-\\\\x{7F}]]*$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.elixir\"\n                        }\n                    },\n                    \"comment\":\n                        \"We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.\",\n                    \"end\": \"$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.elixir\"\n                        }\n                    },\n                    \"name\": \"comment.line.number-sign.elixir\"\n                }\n            ]\n        }\n    },\n    \"scopeName\": \"source.elixir\"\n}\n"
  },
  {
    "path": "extensions/elixir/syntaxes/html(eex).tmLanguage.json",
    "content": "{\n    \"fileTypes\": [\"html.eex\"],\n    \"foldingStartMarker\":\n        \"(?x)\\n\\t\\t(<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)\\\\b.*?>\\n\\t\\t|<!--(?!.*-->)\\n\\t\\t|\\\\{\\\\s*($|\\\\?>\\\\s*$|//|/\\\\*(.*\\\\*/\\\\s*$|(?!.*?\\\\*/)))\\n\\t\\t)\",\n    \"foldingStopMarker\":\n        \"(?x)\\n\\t\\t(</(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)>\\n\\t\\t|^\\\\s*-->\\n\\t\\t|(^|\\\\s)\\\\}\\n\\t\\t)\",\n    \"name\": \"HTML (EEx)\",\n    \"patterns\": [\n        {\n            \"include\": \"text.elixir\"\n        },\n        {\n            \"include\": \"text.html.basic\"\n        }\n    ],\n    \"scopeName\": \"text.html.elixir\"\n}\n"
  },
  {
    "path": "extensions/go/README.md",
    "content": "# Go\n\nThe syntax file for Go is from the VSCode repository: https://github.com/Microsoft/vscode/blob/master/extensions/go/syntaxes/go.json\n"
  },
  {
    "path": "extensions/go/syntaxes/go.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-go/blob/master/grammars/go.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-go/commit/f7c6ca60bfd9d11252560b21e9378e5f82438ce3\",\n    \"scopeName\": \"source.go\",\n    \"name\": \"Go\",\n    \"comment\": \"Go language\",\n    \"fileTypes\": [\"go\"],\n    \"foldingStartMarker\": \"({|\\\\()\\\\s*$\",\n    \"foldingStopMarker\": \"(}|\\\\))\\\\s*$\",\n    \"patterns\": [\n        {\n            \"include\": \"#comments\"\n        },\n        {\n            \"comment\": \"Interpreted string literals\",\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.go\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.go\"\n                }\n            },\n            \"name\": \"string.quoted.double.go\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string_escaped_char\"\n                },\n                {\n                    \"include\": \"#string_placeholder\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Raw string literals\",\n            \"begin\": \"`\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.go\"\n                }\n            },\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.go\"\n                }\n            },\n            \"name\": \"string.quoted.raw.go\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string_placeholder\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Syntax error receiving channels\",\n            \"match\": \"<\\\\-([\\\\t ]+)chan\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.receive-channel.go\"\n                }\n            }\n        },\n        {\n            \"comment\": \"Syntax error sending channels\",\n            \"match\": \"\\\\bchan([\\\\t ]+)<-\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.send-channel.go\"\n                }\n            }\n        },\n        {\n            \"comment\": \"Syntax error using slices\",\n            \"match\": \"\\\\[\\\\](\\\\s+)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.slice.go\"\n                }\n            }\n        },\n        {\n            \"comment\": \"Syntax error numeric literals\",\n            \"match\": \"\\\\b0[0-7]*[89]\\\\d*\\\\b\",\n            \"name\": \"invalid.illegal.numeric.go\"\n        },\n        {\n            \"comment\": \"Built-in functions\",\n            \"match\":\n                \"\\\\b(append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover)\\\\b(?=\\\\()\",\n            \"name\": \"support.function.builtin.go\"\n        },\n        {\n            \"comment\": \"Function declarations\",\n            \"match\": \"^(\\\\bfunc\\\\b)(?:\\\\s+(\\\\([^\\\\)]+\\\\)\\\\s+)?(\\\\w+)(?=\\\\())?\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.function.go\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        },\n                        {\n                            \"include\": \"#operators\"\n                        }\n                    ]\n                },\n                \"3\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\d\\\\w*\",\n                            \"name\": \"invalid.illegal.identifier.go\"\n                        },\n                        {\n                            \"match\": \"\\\\w+\",\n                            \"name\": \"entity.name.function.go\"\n                        }\n                    ]\n                }\n            }\n        },\n        {\n            \"comment\": \"Functions\",\n            \"match\": \"(\\\\bfunc\\\\b)|(\\\\w+)(?=\\\\()\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.function.go\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\d\\\\w*\",\n                            \"name\": \"invalid.illegal.identifier.go\"\n                        },\n                        {\n                            \"match\": \"\\\\w+\",\n                            \"name\": \"support.function.go\"\n                        }\n                    ]\n                }\n            }\n        },\n        {\n            \"comment\": \"Floating-point literals\",\n            \"match\": \"(\\\\.\\\\d+([Ee][-+]\\\\d+)?i?)\\\\b|\\\\b\\\\d+\\\\.\\\\d*(([Ee][-+]\\\\d+)?i?\\\\b)?\",\n            \"name\": \"constant.numeric.floating-point.go\"\n        },\n        {\n            \"comment\": \"Integers\",\n            \"match\":\n                \"\\\\b((0x[0-9a-fA-F]+)|(0[0-7]+i?)|(\\\\d+([Ee]\\\\d+)?i?)|(\\\\d+[Ee][-+]\\\\d+i?))\\\\b\",\n            \"name\": \"constant.numeric.integer.go\"\n        },\n        {\n            \"comment\": \"Language constants\",\n            \"match\": \"\\\\b(true|false|nil|iota)\\\\b\",\n            \"name\": \"constant.language.go\"\n        },\n        {\n            \"begin\": \"\\\\b(package)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.package.go\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\d\\\\w*\",\n                    \"name\": \"invalid.illegal.identifier.go\"\n                },\n                {\n                    \"match\": \"\\\\w+\",\n                    \"name\": \"entity.name.package.go\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\b(type)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.type.go\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\d\\\\w*\",\n                    \"name\": \"invalid.illegal.identifier.go\"\n                },\n                {\n                    \"match\": \"\\\\w+\",\n                    \"name\": \"entity.name.type.go\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\b(import)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.import.go\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#imports\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\b(var)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.var.go\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variables\"\n                }\n            ]\n        },\n        {\n            \"match\": \"(?<!var)\\\\s*(\\\\w+(?:\\\\.\\\\w+)*(?>,\\\\s*\\\\w+(?:\\\\.\\\\w+)*)*)(?=\\\\s*=(?!=))\",\n            \"captures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\d\\\\w*\",\n                            \"name\": \"invalid.illegal.identifier.go\"\n                        },\n                        {\n                            \"match\": \"\\\\w+(?:\\\\.\\\\w+)*\",\n                            \"name\": \"variable.other.assignment.go\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#delimiters\"\n                                        }\n                                    ]\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#delimiters\"\n                        }\n                    ]\n                }\n            }\n        },\n        {\n            \"match\": \"\\\\w+(?:,\\\\s*\\\\w+)*(?=\\\\s*:=)\",\n            \"captures\": {\n                \"0\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\d\\\\w*\",\n                            \"name\": \"invalid.illegal.identifier.go\"\n                        },\n                        {\n                            \"match\": \"\\\\w+\",\n                            \"name\": \"variable.other.assignment.go\"\n                        },\n                        {\n                            \"include\": \"#delimiters\"\n                        }\n                    ]\n                }\n            }\n        },\n        {\n            \"comment\": \"Terminators\",\n            \"match\": \";\",\n            \"name\": \"punctuation.terminator.go\"\n        },\n        {\n            \"include\": \"#brackets\"\n        },\n        {\n            \"include\": \"#delimiters\"\n        },\n        {\n            \"include\": \"#keywords\"\n        },\n        {\n            \"include\": \"#operators\"\n        },\n        {\n            \"include\": \"#runes\"\n        },\n        {\n            \"include\": \"#storage_types\"\n        }\n    ],\n    \"repository\": {\n        \"brackets\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.begin.bracket.curly.go\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.end.bracket.curly.go\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.begin.bracket.round.go\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.end.bracket.round.go\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"\\\\[|\\\\]\",\n                    \"name\": \"punctuation.definition.bracket.square.go\"\n                }\n            ]\n        },\n        \"comments\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"/\\\\*\",\n                    \"end\": \"\\\\*/\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.go\"\n                        }\n                    },\n                    \"name\": \"comment.block.go\"\n                },\n                {\n                    \"begin\": \"//\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.go\"\n                        }\n                    },\n                    \"end\": \"$\",\n                    \"name\": \"comment.line.double-slash.go\"\n                }\n            ]\n        },\n        \"delimiters\": {\n            \"patterns\": [\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.other.comma.go\"\n                },\n                {\n                    \"match\": \"\\\\.(?!\\\\.\\\\.)\",\n                    \"name\": \"punctuation.other.period.go\"\n                },\n                {\n                    \"match\": \":(?!=)\",\n                    \"name\": \"punctuation.other.colon.go\"\n                }\n            ]\n        },\n        \"imports\": {\n            \"patterns\": [\n                {\n                    \"match\": \"((?!\\\\s+\\\")[^\\\\s]*)?\\\\s*((\\\")([^\\\"]*)(\\\"))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.alias.import.go\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.quoted.double.go\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.string.begin.go\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.import.go\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.string.end.go\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.imports.begin.bracket.round.go\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.imports.end.bracket.round.go\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comments\"\n                        },\n                        {\n                            \"include\": \"#imports\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"keywords\": {\n            \"patterns\": [\n                {\n                    \"comment\": \"Flow control keywords\",\n                    \"match\":\n                        \"\\\\b(break|case|continue|default|defer|else|fallthrough|for|go|goto|if|range|return|select|switch)\\\\b\",\n                    \"name\": \"keyword.control.go\"\n                },\n                {\n                    \"match\": \"\\\\bchan\\\\b\",\n                    \"name\": \"keyword.channel.go\"\n                },\n                {\n                    \"match\": \"\\\\bconst\\\\b\",\n                    \"name\": \"keyword.const.go\"\n                },\n                {\n                    \"match\": \"\\\\bfunc\\\\b\",\n                    \"name\": \"keyword.function.go\"\n                },\n                {\n                    \"match\": \"\\\\binterface\\\\b\",\n                    \"name\": \"keyword.interface.go\"\n                },\n                {\n                    \"match\": \"\\\\bmap\\\\b\",\n                    \"name\": \"keyword.map.go\"\n                },\n                {\n                    \"match\": \"\\\\bstruct\\\\b\",\n                    \"name\": \"keyword.struct.go\"\n                }\n            ]\n        },\n        \"operators\": {\n            \"comment\": \"Note that the order here is very important!\",\n            \"patterns\": [\n                {\n                    \"match\": \"(\\\\*|&)(?=\\\\w)\",\n                    \"name\": \"keyword.operator.address.go\"\n                },\n                {\n                    \"match\": \"<\\\\-\",\n                    \"name\": \"keyword.operator.channel.go\"\n                },\n                {\n                    \"match\": \"\\\\-\\\\-\",\n                    \"name\": \"keyword.operator.decrement.go\"\n                },\n                {\n                    \"match\": \"\\\\+\\\\+\",\n                    \"name\": \"keyword.operator.increment.go\"\n                },\n                {\n                    \"match\": \"(==|!=|<=|>=|<[^<]|>[^>])\",\n                    \"name\": \"keyword.operator.comparison.go\"\n                },\n                {\n                    \"match\": \"(&&|\\\\|\\\\||!)\",\n                    \"name\": \"keyword.operator.logical.go\"\n                },\n                {\n                    \"match\": \"(=|\\\\+=|\\\\-=|\\\\|=|\\\\^=|\\\\*=|/=|:=|%=|<<=|>>=|&\\\\^=|&=)\",\n                    \"name\": \"keyword.operator.assignment.go\"\n                },\n                {\n                    \"match\": \"(\\\\+|\\\\-|\\\\*|/|%)\",\n                    \"name\": \"keyword.operator.arithmetic.go\"\n                },\n                {\n                    \"match\": \"(&(?!\\\\^)|\\\\||\\\\^|&\\\\^|<<|>>)\",\n                    \"name\": \"keyword.operator.arithmetic.bitwise.go\"\n                },\n                {\n                    \"match\": \"\\\\.\\\\.\\\\.\",\n                    \"name\": \"keyword.operator.ellipsis.go\"\n                }\n            ]\n        },\n        \"runes\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.go\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.go\"\n                        }\n                    },\n                    \"name\": \"string.quoted.rune.go\",\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"\\\\G(\\\\\\\\([0-7]{3}|[abfnrtv\\\\\\\\'\\\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})|.)(?=')\",\n                            \"name\": \"constant.other.rune.go\"\n                        },\n                        {\n                            \"match\": \"[^']+\",\n                            \"name\": \"invalid.illegal.unknown-rune.go\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"storage_types\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\bbool\\\\b\",\n                    \"name\": \"storage.type.boolean.go\"\n                },\n                {\n                    \"match\": \"\\\\bbyte\\\\b\",\n                    \"name\": \"storage.type.byte.go\"\n                },\n                {\n                    \"match\": \"\\\\berror\\\\b\",\n                    \"name\": \"storage.type.error.go\"\n                },\n                {\n                    \"match\": \"\\\\b(complex(64|128)|float(32|64)|u?int(8|16|32|64)?)\\\\b\",\n                    \"name\": \"storage.type.numeric.go\"\n                },\n                {\n                    \"match\": \"\\\\brune\\\\b\",\n                    \"name\": \"storage.type.rune.go\"\n                },\n                {\n                    \"match\": \"\\\\bstring\\\\b\",\n                    \"name\": \"storage.type.string.go\"\n                },\n                {\n                    \"match\": \"\\\\buintptr\\\\b\",\n                    \"name\": \"storage.type.uintptr.go\"\n                }\n            ]\n        },\n        \"string_escaped_char\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"\\\\\\\\([0-7]{3}|[abfnrtv\\\\\\\\'\\\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})\",\n                    \"name\": \"constant.character.escape.go\"\n                },\n                {\n                    \"match\": \"\\\\\\\\[^0-7xuUabfnrtv\\\\'\\\"]\",\n                    \"name\": \"invalid.illegal.unknown-escape.go\"\n                }\n            ]\n        },\n        \"string_placeholder\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"%(\\\\[\\\\d+\\\\])?([\\\\+#\\\\-0\\\\x20]{,2}((\\\\d+|\\\\*)?(\\\\.?(\\\\d+|\\\\*|(\\\\[\\\\d+\\\\])\\\\*?)?(\\\\[\\\\d+\\\\])?)?))?[vT%tbcdoqxXUbeEfFgGsp]\",\n                    \"name\": \"constant.other.placeholder.go\"\n                }\n            ]\n        },\n        \"variables\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(\\\\w+(?:,\\\\s*\\\\w+)*)(\\\\s+\\\\*?\\\\w+(?:\\\\.\\\\w+)?\\\\s*)?(?=\\\\s*=)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\d\\\\w*\",\n                                    \"name\": \"invalid.illegal.identifier.go\"\n                                },\n                                {\n                                    \"match\": \"\\\\w+\",\n                                    \"name\": \"variable.other.assignment.go\"\n                                },\n                                {\n                                    \"include\": \"#delimiters\"\n                                }\n                            ]\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(\\\\w+(?:,\\\\s*\\\\w+)*)(\\\\s+(\\\\[(\\\\d*|\\\\.\\\\.\\\\.)\\\\])*\\\\*?(<-)?\\\\w+(?:\\\\.\\\\w+)?\\\\s*[^=].*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\d\\\\w*\",\n                                    \"name\": \"invalid.illegal.identifier.go\"\n                                },\n                                {\n                                    \"match\": \"\\\\w+\",\n                                    \"name\": \"variable.other.declaration.go\"\n                                },\n                                {\n                                    \"include\": \"#delimiters\"\n                                }\n                            ]\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variables.begin.bracket.round.go\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variables.end.bracket.round.go\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        },\n                        {\n                            \"include\": \"#variables\"\n                        }\n                    ]\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/html/package.json",
    "content": "{\n    \"name\": \"html\",\n    \"version\": \"0.0.1\",\n    \"description\": \"HTML extension for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"snippets\": [\n            {\n                \"language\": \"html\",\n                \"path\": \"snippets/html.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/html/snippets/html.json",
    "content": "{\n    \"HTML template\": {\n        \"prefix\": \"html\",\n        \"body\": [\n            \"<!DOCTYPE html>\",\n            \"<html>\",\n            \"<head>\",\n            \"\\t<meta charset=\\\"utf-8\\\" />\",\n            \"\\t<meta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\">\",\n            \"\\t<title>${1:Page Title}</title>\",\n            \"\\t<meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1\\\">\",\n            \"\\t<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" media=\\\"screen\\\" href=\\\"${2:main.css}\\\" />\",\n            \"\\t<script src=\\\"${3:main.js}\\\"></script>\",\n            \"</head>\",\n            \"<body>\",\n            \"\\t$0\",\n            \"</body>\",\n            \"</html>\"\n        ],\n        \"description\": \"Simple HTML5 starting point\"\n    }\n}\n"
  },
  {
    "path": "extensions/images/package.json",
    "content": "{\n    \"name\": \"images\",\n    \"version\": \"0.0.1\",\n    \"description\": \"Images plugin for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"languages\": [\n            {\n                \"id\": \"image\",\n                \"extensions\": [\".gif\", \".jpg\", \".jpeg\", \".bmp\", \".svg\", \".png\"]\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/java/syntaxes/Java.tmLanguage.json",
    "content": "{\n    \"scopeName\": \"source.java\",\n    \"name\": \"Java\",\n    \"fileTypes\": [\"java\", \"bsh\"],\n    \"patterns\": [\n        {\n            \"begin\": \"\\\\b(package)\\\\b\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.package.java\"\n                }\n            },\n            \"end\": \"\\\\s*(;)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.terminator.java\"\n                }\n            },\n            \"name\": \"meta.package.java\",\n            \"contentName\": \"storage.modifier.package.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"match\": \"(?<=\\\\.)\\\\s*\\\\.|\\\\.(?=\\\\s*;)\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\": \"(?<!_)_(?=\\\\s*(\\\\.|;))|\\\\b\\\\d+|-+\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\": \"[A-Z]+\",\n                    \"name\": \"invalid.deprecated.package_name_not_lowercase.java\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\\\b(?<!\\\\$)\\n(abstract|assert|boolean|break|byte|case|catch|char|class|\\nconst|continue|default|do|double|else|enum|extends|final|\\nfinally|float|for|goto|if|implements|import|instanceof|int|\\ninterface|long|native|new|package|private|protected|public|\\nreturn|short|static|strictfp|super|switch|syncronized|this|\\nthrow|throws|transient|try|void|volatile|while|\\ntrue|false|null)\\\\b\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\": \"\\\\.\",\n                    \"name\": \"punctuation.separator.java\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\b(import)\\\\b\\\\s*\\\\b(static)?\\\\b\\\\s\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.import.java\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.java\"\n                }\n            },\n            \"end\": \"\\\\s*(;)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.terminator.java\"\n                }\n            },\n            \"name\": \"meta.import.java\",\n            \"contentName\": \"storage.modifier.import.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"match\": \"(?<=\\\\.)\\\\s*\\\\.|\\\\.(?=\\\\s*;)\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\": \"(?<!\\\\.)\\\\s*\\\\*\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\": \"(?<!_)_(?=\\\\s*(\\\\.|;))|\\\\b\\\\d+|-+\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\\\b(?<!\\\\$)\\n(abstract|assert|boolean|break|byte|case|catch|char|class|\\nconst|continue|default|do|double|else|enum|extends|final|\\nfinally|float|for|goto|if|implements|import|instanceof|int|\\ninterface|long|native|new|package|private|protected|public|\\nreturn|short|static|strictfp|super|switch|syncronized|this|\\nthrow|throws|transient|try|void|volatile|while|\\ntrue|false|null)\\\\b\",\n                    \"name\": \"invalid.illegal.character_not_allowed_here.java\"\n                },\n                {\n                    \"match\": \"\\\\.\",\n                    \"name\": \"punctuation.separator.java\"\n                },\n                {\n                    \"match\": \"\\\\*\",\n                    \"name\": \"variable.language.wildcard.java\"\n                }\n            ]\n        },\n        {\n            \"include\": \"#comments-javadoc\"\n        },\n        {\n            \"include\": \"#code\"\n        }\n    ],\n    \"repository\": {\n        \"all-types\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#primitive-arrays\"\n                },\n                {\n                    \"include\": \"#primitive-types\"\n                },\n                {\n                    \"include\": \"#object-types\"\n                }\n            ]\n        },\n        \"annotations\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"((@)[^\\\\s(]+)(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.annotation.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.annotation.java\"\n                        },\n                        \"3\": {\n                            \"name\":\n                                \"punctuation.definition.annotation-arguments.begin.bracket.round.java\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\":\n                                \"punctuation.definition.annotation-arguments.end.bracket.round.java\"\n                        }\n                    },\n                    \"name\": \"meta.declaration.annotation.java\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"constant.other.key.java\"\n                                },\n                                \"2\": {\n                                    \"name\": \"keyword.operator.assignment.java\"\n                                }\n                            },\n                            \"match\": \"(\\\\w*)\\\\s*(=)\"\n                        },\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(@)(interface)\\\\s+(\\\\w*)|((@)\\\\w*)\",\n                    \"name\": \"meta.declaration.annotation.java\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.annotation.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.java\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.annotation.java\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.annotation.java\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.annotation.java\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"anonymous-classes-and-new\": {\n            \"begin\": \"\\\\bnew\\\\b\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.control.new.java\"\n                }\n            },\n            \"end\": \"(?=;|\\\\)|,|:|}|\\\\+)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#all-types\"\n                },\n                {\n                    \"begin\": \"(?<!\\\\])\\\\s*({)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.inner-class.begin.bracket.curly.java\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.inner-class.end.bracket.curly.java\"\n                        }\n                    },\n                    \"name\": \"meta.inner-class.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#class-body\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#parens\"\n                }\n            ]\n        },\n        \"assertions\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(assert)\\\\s\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.assert.java\"\n                        }\n                    },\n                    \"end\": \"$\",\n                    \"name\": \"meta.declaration.assertion.java\",\n                    \"patterns\": [\n                        {\n                            \"match\": \":\",\n                            \"name\": \"keyword.operator.assert.expression-separator.java\"\n                        },\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"class\": {\n            \"begin\": \"(?=\\\\w?[\\\\w\\\\s]*(?:class|(?<!@)interface|enum)\\\\s+\\\\w+)\",\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.class.end.bracket.curly.java\"\n                }\n            },\n            \"name\": \"meta.class.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#storage-modifiers\"\n                },\n                {\n                    \"include\": \"#generics\"\n                },\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.type.class.java\"\n                        }\n                    },\n                    \"match\": \"(class|(?<!@)interface|enum)\\\\s+(\\\\w+)\",\n                    \"name\": \"meta.class.identifier.java\"\n                },\n                {\n                    \"begin\": \"extends\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.modifier.extends.java\"\n                        }\n                    },\n                    \"end\": \"(?={|implements)\",\n                    \"name\": \"meta.definition.class.inherited.classes.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-types-inherited\"\n                        },\n                        {\n                            \"include\": \"#comments\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(implements)\\\\s\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.implements.java\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s*extends|\\\\{)\",\n                    \"name\": \"meta.definition.class.implemented.interfaces.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-types-inherited\"\n                        },\n                        {\n                            \"include\": \"#comments\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.class.begin.bracket.curly.java\"\n                        }\n                    },\n                    \"end\": \"(?=})\",\n                    \"contentName\": \"meta.class.body.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#class-body\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"class-body\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comments-javadoc\"\n                },\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"include\": \"#class\"\n                },\n                {\n                    \"include\": \"#enums\"\n                },\n                {\n                    \"include\": \"#generics\"\n                },\n                {\n                    \"include\": \"#static-initializer\"\n                },\n                {\n                    \"include\": \"#methods\"\n                },\n                {\n                    \"include\": \"#annotations\"\n                },\n                {\n                    \"include\": \"#member-variables\"\n                },\n                {\n                    \"include\": \"#storage-modifiers\"\n                },\n                {\n                    \"include\": \"#code\"\n                }\n            ]\n        },\n        \"anonymous-block-and-instance-initializer\": {\n            \"begin\": \"{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.block.begin.bracket.curly.java\"\n                }\n            },\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.block.end.bracket.curly.java\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#code\"\n                }\n            ]\n        },\n        \"static-initializer\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#anonymous-block-and-instance-initializer\"\n                },\n                {\n                    \"match\": \"static\",\n                    \"name\": \"storage.modifier.java\"\n                }\n            ]\n        },\n        \"code\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#annotations\"\n                },\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"include\": \"#enums\"\n                },\n                {\n                    \"include\": \"#class\"\n                },\n                {\n                    \"include\": \"#anonymous-block-and-instance-initializer\"\n                },\n                {\n                    \"include\": \"#try-catch-finally\"\n                },\n                {\n                    \"include\": \"#assertions\"\n                },\n                {\n                    \"include\": \"#parens\"\n                },\n                {\n                    \"include\": \"#constants-and-special-vars\"\n                },\n                {\n                    \"include\": \"#numbers\"\n                },\n                {\n                    \"include\": \"#anonymous-classes-and-new\"\n                },\n                {\n                    \"include\": \"#lambda-expression\"\n                },\n                {\n                    \"include\": \"#keywords\"\n                },\n                {\n                    \"include\": \"#storage-modifiers\"\n                },\n                {\n                    \"include\": \"#method-call\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#objects\"\n                },\n                {\n                    \"include\": \"#properties\"\n                },\n                {\n                    \"include\": \"#variables\"\n                },\n                {\n                    \"include\": \"#strings\"\n                },\n                {\n                    \"include\": \"#all-types\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.java\"\n                },\n                {\n                    \"match\": \"\\\\.\",\n                    \"name\": \"punctuation.separator.period.java\"\n                },\n                {\n                    \"match\": \";\",\n                    \"name\": \"punctuation.terminator.java\"\n                }\n            ]\n        },\n        \"comments\": {\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.java\"\n                        }\n                    },\n                    \"match\": \"/\\\\*\\\\*/\",\n                    \"name\": \"comment.block.empty.java\"\n                },\n                {\n                    \"include\": \"text.html.javadoc\"\n                },\n                {\n                    \"include\": \"#comments-inline\"\n                }\n            ]\n        },\n        \"comments-inline\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"/\\\\*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.java\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"name\": \"comment.block.java\"\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?(?=//)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.java\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"//\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.java\"\n                                }\n                            },\n                            \"end\": \"\\\\n\",\n                            \"name\": \"comment.line.double-slash.java\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"comments-javadoc\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*/\\\\*\\\\*(?!/)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.java\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.java\"\n                        }\n                    },\n                    \"name\": \"comment.block.javadoc.java\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"@(author|deprecated|return|see|serial|since|version)\\\\b\",\n                            \"name\": \"keyword.other.documentation.javadoc.java\"\n                        },\n                        {\n                            \"match\": \"(@param)\\\\s+(\\\\S+)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.documentation.javadoc.java\"\n                                },\n                                \"2\": {\n                                    \"name\": \"variable.parameter.java\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"(@(?:exception|throws))\\\\s+(\\\\S+)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.documentation.javadoc.java\"\n                                },\n                                \"2\": {\n                                    \"name\": \"entity.name.type.class.java\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"{(@link)\\\\s+(\\\\S+)?#([\\\\w$]+\\\\s*\\\\([^\\\\(\\\\)]*\\\\)).*}\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.documentation.javadoc.java\"\n                                },\n                                \"2\": {\n                                    \"name\": \"entity.name.type.class.java\"\n                                },\n                                \"3\": {\n                                    \"name\": \"variable.parameter.java\"\n                                }\n                            }\n                        }\n                    ]\n                }\n            ]\n        },\n        \"try-catch-finally\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\btry\\\\b\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.try.java\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.try.end.bracket.curly.java\"\n                        }\n                    },\n                    \"name\": \"meta.try.java\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\(\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.section.try.resources.begin.bracket.round.java\"\n                                }\n                            },\n                            \"end\": \"\\\\)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.section.try.resources.end.bracket.round.java\"\n                                }\n                            },\n                            \"name\": \"meta.try.resources.java\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#code\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.try.begin.bracket.curly.java\"\n                                }\n                            },\n                            \"end\": \"(?=})\",\n                            \"contentName\": \"meta.try.body.java\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#code\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b(catch)\\\\b\\\\s*(?=\\\\(\\\\s*[^\\\\s]+\\\\s*[^)]+\\\\))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.catch.java\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.catch.end.bracket.curly.java\"\n                        }\n                    },\n                    \"name\": \"meta.catch.java\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\(\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.parameters.begin.bracket.round.java\"\n                                }\n                            },\n                            \"end\": \"\\\\)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.parameters.end.bracket.round.java\"\n                                }\n                            },\n                            \"contentName\": \"meta.catch.parameters.java\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comments\"\n                                },\n                                {\n                                    \"include\": \"#parameters\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.catch.begin.bracket.curly.java\"\n                                }\n                            },\n                            \"end\": \"(?=})\",\n                            \"contentName\": \"meta.catch.body.java\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#code\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\bfinally\\\\b\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.finally.java\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.finally.end.bracket.curly.java\"\n                        }\n                    },\n                    \"name\": \"meta.finally.java\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.section.finally.begin.bracket.curly.java\"\n                                }\n                            },\n                            \"end\": \"(?=})\",\n                            \"contentName\": \"meta.finally.body.java\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#code\"\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"constants-and-special-vars\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(true|false|null)\\\\b\",\n                    \"name\": \"constant.language.java\"\n                },\n                {\n                    \"match\": \"\\\\bthis\\\\b\",\n                    \"name\": \"variable.language.this.java\"\n                },\n                {\n                    \"match\": \"\\\\bsuper\\\\b\",\n                    \"name\": \"variable.language.java\"\n                }\n            ]\n        },\n        \"generics\": {\n            \"begin\": \"<\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.bracket.angle.java\"\n                }\n            },\n            \"end\": \">\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.bracket.angle.java\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(extends|super)\\\\b\",\n                    \"name\": \"storage.modifier.$1.java\"\n                },\n                {\n                    \"match\": \"(?<!\\\\.)([a-zA-Z$_][a-zA-Z0-9$_]*)(?=\\\\s*<)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.java\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#primitive-arrays\"\n                },\n                {\n                    \"match\": \"[a-zA-Z$_][a-zA-Z0-9$_]*\",\n                    \"name\": \"storage.type.generic.java\"\n                },\n                {\n                    \"match\": \"\\\\?\",\n                    \"name\": \"storage.type.generic.wildcard.java\"\n                },\n                {\n                    \"match\": \"&\",\n                    \"name\": \"punctuation.separator.types.java\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.java\"\n                },\n                {\n                    \"match\": \"\\\\.\",\n                    \"name\": \"punctuation.separator.period.java\"\n                },\n                {\n                    \"include\": \"#parens\"\n                },\n                {\n                    \"include\": \"#generics\"\n                },\n                {\n                    \"include\": \"#comments\"\n                }\n            ]\n        },\n        \"enums\": {\n            \"begin\": \"^\\\\s*(enum)\\\\s+(\\\\w+)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.java\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.enum.java\"\n                }\n            },\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.enum.end.bracket.curly.java\"\n                }\n            },\n            \"name\": \"meta.enum.java\",\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.enum.begin.bracket.curly.java\"\n                        }\n                    },\n                    \"end\": \"(?=})\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\w+\",\n                            \"name\": \"constant.other.enum.java\"\n                        },\n                        {\n                            \"include\": \"#class-body\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comments\"\n                }\n            ]\n        },\n        \"function-call\": {\n            \"begin\": \"([A-Za-z_$][\\\\w$]*)\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.java\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.parameters.begin.bracket.round.java\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.bracket.round.java\"\n                }\n            },\n            \"name\": \"meta.function-call.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#code\"\n                }\n            ]\n        },\n        \"keywords\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\bthrow\\\\b\",\n                    \"name\": \"keyword.control.throw.java\"\n                },\n                {\n                    \"match\": \"\\\\?|:\",\n                    \"name\": \"keyword.control.ternary.java\"\n                },\n                {\n                    \"match\":\n                        \"\\\\b(return|break|case|continue|default|do|while|for|switch|if|else)\\\\b\",\n                    \"name\": \"keyword.control.java\"\n                },\n                {\n                    \"match\": \"\\\\b(instanceof)\\\\b\",\n                    \"name\": \"keyword.operator.instanceof.java\"\n                },\n                {\n                    \"match\": \"(<<|>>>?|~|\\\\^)\",\n                    \"name\": \"keyword.operator.bitwise.java\"\n                },\n                {\n                    \"match\": \"((&|\\\\^|\\\\||<<|>>>?)=)\",\n                    \"name\": \"keyword.operator.assignment.bitwise.java\"\n                },\n                {\n                    \"match\": \"(===?|!=|<=|>=|<>|<|>)\",\n                    \"name\": \"keyword.operator.comparison.java\"\n                },\n                {\n                    \"match\": \"([+*/%-]=)\",\n                    \"name\": \"keyword.operator.assignment.arithmetic.java\"\n                },\n                {\n                    \"match\": \"(=)\",\n                    \"name\": \"keyword.operator.assignment.java\"\n                },\n                {\n                    \"match\": \"(\\\\-\\\\-|\\\\+\\\\+)\",\n                    \"name\": \"keyword.operator.increment-decrement.java\"\n                },\n                {\n                    \"match\": \"(\\\\-|\\\\+|\\\\*|\\\\/|%)\",\n                    \"name\": \"keyword.operator.arithmetic.java\"\n                },\n                {\n                    \"match\": \"(!|&&|\\\\|\\\\|)\",\n                    \"name\": \"keyword.operator.logical.java\"\n                },\n                {\n                    \"match\": \"(\\\\||&)\",\n                    \"name\": \"keyword.operator.bitwise.java\"\n                },\n                {\n                    \"match\": \"\\\\b(const|goto)\\\\b\",\n                    \"name\": \"keyword.reserved.java\"\n                }\n            ]\n        },\n        \"lambda-expression\": {\n            \"patterns\": [\n                {\n                    \"match\": \"->\",\n                    \"name\": \"storage.type.function.arrow.java\"\n                }\n            ]\n        },\n        \"method-call\": {\n            \"begin\": \"(\\\\.)\\\\s*([A-Za-z_$][\\\\w$]*)\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.period.java\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.java\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.parameters.begin.bracket.round.java\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.bracket.round.java\"\n                }\n            },\n            \"name\": \"meta.method-call.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#code\"\n                }\n            ]\n        },\n        \"methods\": {\n            \"begin\": \"(?!new)(?=[\\\\w<].*\\\\s+)(?=([^=/]|/(?!/))+\\\\()\",\n            \"end\": \"(})|(?=;)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.method.end.bracket.curly.java\"\n                }\n            },\n            \"name\": \"meta.method.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#storage-modifiers\"\n                },\n                {\n                    \"begin\": \"(\\\\w+)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.parameters.begin.bracket.round.java\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.end.bracket.round.java\"\n                        }\n                    },\n                    \"name\": \"meta.method.identifier.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameters\"\n                        },\n                        {\n                            \"include\": \"#parens\"\n                        },\n                        {\n                            \"include\": \"#comments-inline\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#generics\"\n                },\n                {\n                    \"begin\": \"(?=\\\\w.*\\\\s+\\\\w+\\\\s*\\\\()\",\n                    \"end\": \"(?=\\\\s+\\\\w+\\\\s*\\\\()\",\n                    \"name\": \"meta.method.return-type.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#all-types\"\n                        },\n                        {\n                            \"include\": \"#parens\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#throws\"\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.method.begin.bracket.curly.java\"\n                        }\n                    },\n                    \"end\": \"(?=})\",\n                    \"contentName\": \"meta.method.body.java\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comments\"\n                }\n            ]\n        },\n        \"numbers\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?x)\\n\\\\b(?<!\\\\$)\\n0(x|X)\\n(\\n  (?<!\\\\.)[0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])?[Ll]?(?!\\\\.)\\n  |\\n  (\\n    [0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])?\\\\.?\\n    |\\n    ([0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])?)?\\\\.[0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])?\\n  )\\n  [Pp][+-]?[0-9]([0-9_]*[0-9])?[FfDd]?\\n)\\n\\\\b(?!\\\\$)\",\n                    \"name\": \"constant.numeric.hex.java\"\n                },\n                {\n                    \"match\": \"\\\\b(?<!\\\\$)0(b|B)[01]([01_]*[01])?[Ll]?\\\\b(?!\\\\$)\",\n                    \"name\": \"constant.numeric.binary.java\"\n                },\n                {\n                    \"match\": \"\\\\b(?<!\\\\$)0[0-7]([0-7_]*[0-7])?[Ll]?\\\\b(?!\\\\$)\",\n                    \"name\": \"constant.numeric.octal.java\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(?<!\\\\$)\\n(\\n  \\\\b[0-9]([0-9_]*[0-9])?\\\\.\\\\B(?!\\\\.)\\n  |\\n  \\\\b[0-9]([0-9_]*[0-9])?\\\\.([Ee][+-]?[0-9]([0-9_]*[0-9])?)[FfDd]?\\\\b\\n  |\\n  \\\\b[0-9]([0-9_]*[0-9])?\\\\.([Ee][+-]?[0-9]([0-9_]*[0-9])?)?[FfDd]\\\\b\\n  |\\n  \\\\b[0-9]([0-9_]*[0-9])?\\\\.([0-9]([0-9_]*[0-9])?)([Ee][+-]?[0-9]([0-9_]*[0-9])?)?[FfDd]?\\\\b\\n  |\\n  (?<!\\\\.)\\\\B\\\\.[0-9]([0-9_]*[0-9])?([Ee][+-]?[0-9]([0-9_]*[0-9])?)?[FfDd]?\\\\b\\n  |\\n  \\\\b[0-9]([0-9_]*[0-9])?([Ee][+-]?[0-9]([0-9_]*[0-9])?)[FfDd]?\\\\b\\n  |\\n  \\\\b[0-9]([0-9_]*[0-9])?([Ee][+-]?[0-9]([0-9_]*[0-9])?)?[FfDd]\\\\b\\n  |\\n  \\\\b(0|[1-9]([0-9_]*[0-9])?)(?!\\\\.)[Ll]?\\\\b\\n)\\n(?!\\\\$)\",\n                    \"name\": \"constant.numeric.decimal.java\"\n                }\n            ]\n        },\n        \"object-types\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#generics\"\n                },\n                {\n                    \"begin\": \"\\\\b(?:[A-Z]\\\\w*\\\\s*(\\\\.)\\\\s*)*([A-Z]\\\\w*)\\\\s*(?=\\\\[)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.object.array.java\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\s*\\\\[)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comments\"\n                        },\n                        {\n                            \"include\": \"#parens\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b((?:[A-Z]\\\\w*\\\\s*(\\\\.)\\\\s*)*[A-Z]\\\\w*)\\\\s*(?=<)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        }\n                    },\n                    \"end\": \"(?<=>)|(?!;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#generics\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"\\\\b(?:[A-Z]\\\\w*\\\\s*(\\\\.)\\\\s*)*[A-Z]\\\\w*\\\\b((?=\\\\s*[A-Za-z$_\\\\n])|(?=\\\\s*\\\\.\\\\.\\\\.))\",\n                    \"name\": \"storage.type.java\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"object-types-inherited\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#generics\"\n                },\n                {\n                    \"match\": \"\\\\b(?:[A-Z]\\\\w*\\\\s*(\\\\.)\\\\s*)*[A-Z]\\\\w*\\\\b\",\n                    \"name\": \"entity.other.inherited-class.java\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.java\"\n                }\n            ]\n        },\n        \"objects\": {\n            \"match\": \"(?<![\\\\w$])[a-zA-Z_$][\\\\w$]*(?=\\\\s*\\\\.\\\\s*[\\\\w$]+)\",\n            \"name\": \"variable.other.object.java\"\n        },\n        \"parameters\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\bfinal\\\\b\",\n                    \"name\": \"storage.modifier.java\"\n                },\n                {\n                    \"include\": \"#annotations\"\n                },\n                {\n                    \"include\": \"#all-types\"\n                },\n                {\n                    \"include\": \"#strings\"\n                },\n                {\n                    \"match\": \"\\\\w+\",\n                    \"name\": \"variable.parameter.java\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.java\"\n                },\n                {\n                    \"match\": \"\\\\.\\\\.\\\\.\",\n                    \"name\": \"punctuation.definition.parameters.varargs.java\"\n                }\n            ]\n        },\n        \"parens\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.bracket.round.java\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.bracket.round.java\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\[\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.bracket.square.java\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.bracket.square.java\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.bracket.curly.java\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.bracket.curly.java\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"primitive-arrays\": {\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"\\\\b(void|boolean|byte|char|short|int|float|long|double)\\\\b\\\\s*(?=\\\\[)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.primitive.array.java\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\s*\\\\[)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comments\"\n                        },\n                        {\n                            \"include\": \"#parens\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"primitive-types\": {\n            \"match\": \"\\\\b(void|boolean|byte|char|short|int|float|long|double)\\\\b\",\n            \"name\": \"storage.type.primitive.java\"\n        },\n        \"properties\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(\\\\.)\\\\s*([a-zA-Z_$][\\\\w$]*)(?=\\\\s*\\\\.\\\\s*[a-zA-Z_$][\\\\w$]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.object.property.java\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([a-zA-Z_$][\\\\w$]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.property.java\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([0-9][\\\\w$]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.period.java\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.identifier.java\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"storage-modifiers\": {\n            \"match\":\n                \"\\\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient|volatile|default|strictfp)\\\\b\",\n            \"name\": \"storage.modifier.java\"\n        },\n        \"strings\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\"\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.java\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.java\"\n                        }\n                    },\n                    \"name\": \"string.quoted.double.java\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\.\",\n                            \"name\": \"constant.character.escape.java\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.java\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.java\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.java\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\.\",\n                            \"name\": \"constant.character.escape.java\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"throws\": {\n            \"begin\": \"throws\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"storage.modifier.java\"\n                }\n            },\n            \"end\": \"(?={|;)\",\n            \"name\": \"meta.throwables.java\",\n            \"patterns\": [\n                {\n                    \"include\": \"#object-types\"\n                }\n            ]\n        },\n        \"variables\": {\n            \"begin\":\n                \"(?x)\\n(?=\\n  (\\n    (void|boolean|byte|char|short|int|float|long|double)\\n    |\\n    (?>(\\\\w+\\\\.)*[A-Z]+\\\\w*) # e.g. `javax.ws.rs.Response`, or `String`\\n  )\\n  (\\n    <[\\\\w<>,\\\\.?\\\\s]*> # e.g. `HashMap<Integer, String>`, or `List<java.lang.String>`\\n  )?\\n  (\\n    (\\\\[\\\\])* # int[][]\\n  )?\\n  \\\\s+\\n  [A-Za-z_$][\\\\w$]* # At least one identifier after space\\n  ([\\\\w\\\\[\\\\],$][\\\\w\\\\[\\\\],\\\\s]*)? # possibly primitive array or additional identifiers\\n  \\\\s*(=|;)\\n)\",\n            \"end\": \"(?=;)\",\n            \"name\": \"meta.definition.variable.java\",\n            \"patterns\": [\n                {\n                    \"match\": \"([A-Za-z$_][\\\\w$]*)(?=\\\\s*(\\\\[\\\\])*\\\\s*(;|=|,))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.definition.java\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#all-types\"\n                },\n                {\n                    \"begin\": \"=\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.assignment.java\"\n                        }\n                    },\n                    \"end\": \"(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#code\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#code\"\n                }\n            ]\n        },\n        \"member-variables\": {\n            \"begin\":\n                \"(?=private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final)\",\n            \"end\": \"(?=;)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#storage-modifiers\"\n                },\n                {\n                    \"include\": \"#variables\"\n                },\n                {\n                    \"include\": \"#primitive-arrays\"\n                },\n                {\n                    \"include\": \"#object-types\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/javascript/package.json",
    "content": "{\n    \"name\": \"JavaScript\",\n    \"version\": \"0.0.1\",\n    \"description\": \"JavaScript extension for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"snippets\": [\n            {\n                \"language\": \"javascript\",\n                \"path\": \"snippets/javascript.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/javascript/snippets/javascript.json",
    "content": "{\n    \"define module\": {\n        \"prefix\": \"define\",\n        \"body\": [\n            \"define([\",\n            \"\\t'require',\",\n            \"\\t'${1:dependency}'\",\n            \"], function(require, ${2:factory}) {\",\n            \"\\t'use strict';\",\n            \"\\t$0\",\n            \"});\"\n        ],\n        \"description\": \"define module\"\n    },\n    \"For Loop\": {\n        \"prefix\": \"for\",\n        \"body\": [\n            \"for (let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++) {\",\n            \"\\tconst ${3:element} = ${2:array}[${1:index}];\",\n            \"\\t$0\",\n            \"}\"\n        ],\n        \"description\": \"For Loop\"\n    },\n    \"For-Each Loop\": {\n        \"prefix\": \"foreach\",\n        \"body\": [\"${1:array}.forEach(${2:element} => {\", \"\\t$0\", \"});\"],\n        \"description\": \"For-Each Loop\"\n    },\n    \"For-In Loop\": {\n        \"prefix\": \"forin\",\n        \"body\": [\n            \"for (const ${1:key} in ${2:object}) {\",\n            \"\\tif (${2:object}.hasOwnProperty(${1:key})) {\",\n            \"\\t\\tconst ${3:element} = ${2:object}[${1:key}];\",\n            \"\\t\\t$0\",\n            \"\\t}\",\n            \"}\"\n        ],\n        \"description\": \"For-In Loop\"\n    },\n    \"For-Of Loop\": {\n        \"prefix\": \"forof\",\n        \"body\": [\"for (const ${1:iterator} of ${2:object}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"For-Of Loop\"\n    },\n    \"Function Statement\": {\n        \"prefix\": \"function\",\n        \"body\": [\"function ${1:name}(${2:params}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"Function Statement\"\n    },\n    \"If Statement\": {\n        \"prefix\": \"if\",\n        \"body\": [\"if (${1:condition}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"If Statement\"\n    },\n    \"If-Else Statement\": {\n        \"prefix\": \"ifelse\",\n        \"body\": [\"if (${1:condition}) {\", \"\\t$0\", \"} else {\", \"\\t\", \"}\"],\n        \"description\": \"If-Else Statement\"\n    },\n    \"New Statement\": {\n        \"prefix\": \"new\",\n        \"body\": [\"const ${1:name} = new ${2:type}(${3:arguments});$0\"],\n        \"description\": \"New Statement\"\n    },\n    \"Switch Statement\": {\n        \"prefix\": \"switch\",\n        \"body\": [\n            \"switch (${1:key}) {\",\n            \"\\tcase ${2:value}:\",\n            \"\\t\\t$0\",\n            \"\\t\\tbreak;\",\n            \"\",\n            \"\\tdefault:\",\n            \"\\t\\tbreak;\",\n            \"}\"\n        ],\n        \"description\": \"Switch Statement\"\n    },\n    \"While Statement\": {\n        \"prefix\": \"while\",\n        \"body\": [\"while (${1:condition}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"While Statement\"\n    },\n    \"Do-While Statement\": {\n        \"prefix\": \"dowhile\",\n        \"body\": [\"do {\", \"\\t$0\", \"} while (${1:condition});\"],\n        \"description\": \"Do-While Statement\"\n    },\n    \"Try-Catch Statement\": {\n        \"prefix\": \"trycatch\",\n        \"body\": [\"try {\", \"\\t$0\", \"} catch (${1:error}) {\", \"\\t\", \"}\"],\n        \"description\": \"Try-Catch Statement\"\n    },\n    \"Set Timeout Function\": {\n        \"prefix\": \"settimeout\",\n        \"body\": [\"setTimeout(() => {\", \"\\t$0\", \"}, ${1:timeout});\"],\n        \"description\": \"Set Timeout Function\"\n    },\n    \"Import external module.\": {\n        \"prefix\": \"import statement\",\n        \"body\": [\"import { $0 } from \\\"${1:module}\\\";\"],\n        \"description\": \"Import external module.\"\n    },\n    \"Region Start\": {\n        \"prefix\": \"#region\",\n        \"body\": [\"//#region $0\"],\n        \"description\": \"Folding Region Start\"\n    },\n    \"Region End\": {\n        \"prefix\": \"#endregion\",\n        \"body\": [\"//#endregion\"],\n        \"description\": \"Folding Region End\"\n    },\n    \"Log to the console\": {\n        \"prefix\": \"log\",\n        \"body\": [\"console.log($1);\", \"$0\"],\n        \"description\": \"Log to the console\"\n    },\n    \"Log warning to console\": {\n        \"prefix\": \"warn\",\n        \"body\": [\"console.warn($1);\", \"$0\"],\n        \"description\": \"Log warning to the console\"\n    },\n    \"Log error to console\": {\n        \"prefix\": \"error\",\n        \"body\": [\"console.error($1);\", \"$0\"],\n        \"description\": \"Log error to the console\"\n    }\n}\n"
  },
  {
    "path": "extensions/javascript/syntaxes/JavaScript.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/Microsoft/TypeScript-TmLanguage/commit/8361b1a232501c67911c81a4664a9460d7922c6b\",\n    \"name\": \"JavaScript (with React support)\",\n    \"scopeName\": \"source.js\",\n    \"fileTypes\": [\".js\", \".jsx\", \".es6\", \".mjs\"],\n    \"uuid\": \"805375ec-d614-41f5-8993-5843fe63ea82\",\n    \"patterns\": [\n        {\n            \"include\": \"#directives\"\n        },\n        {\n            \"include\": \"#statements\"\n        },\n        {\n            \"name\": \"comment.line.shebang.ts\",\n            \"match\": \"\\\\A(#!).*(?=$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.ts\"\n                }\n            }\n        }\n    ],\n    \"repository\": {\n        \"statements\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#declaration\"\n                },\n                {\n                    \"include\": \"#control-statement\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#function-declaration\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#interface-declaration\"\n                },\n                {\n                    \"include\": \"#enum-declaration\"\n                },\n                {\n                    \"include\": \"#namespace-declaration\"\n                },\n                {\n                    \"include\": \"#type-alias-declaration\"\n                },\n                {\n                    \"include\": \"#import-equals-declaration\"\n                },\n                {\n                    \"include\": \"#import-declaration\"\n                },\n                {\n                    \"include\": \"#export-declaration\"\n                }\n            ]\n        },\n        \"control-statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#switch-statement\"\n                },\n                {\n                    \"include\": \"#for-loop\"\n                },\n                {\n                    \"name\": \"keyword.control.trycatch.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(catch|finally|throw|try)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.loop.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(break|continue|do|goto|while)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.flow.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(return)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.switch.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(case|default|switch)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.conditional.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(else|if)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.with.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(with)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.other.debugger.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(debugger)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"storage.modifier.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(declare)\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#regex\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#function-expression\"\n                },\n                {\n                    \"include\": \"#class-expression\"\n                },\n                {\n                    \"include\": \"#arrow-function\"\n                },\n                {\n                    \"include\": \"#cast\"\n                },\n                {\n                    \"include\": \"#ternary-expression\"\n                },\n                {\n                    \"include\": \"#new-expr\"\n                },\n                {\n                    \"include\": \"#object-literal\"\n                },\n                {\n                    \"include\": \"#expression-operators\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#literal\"\n                },\n                {\n                    \"include\": \"#support-objects\"\n                },\n                {\n                    \"include\": \"#identifiers\"\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                }\n            ]\n        },\n        \"decorator\": {\n            \"name\": \"meta.decorator.js\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\@\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.decorator.js\"\n                }\n            },\n            \"end\": \"(?=\\\\s)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"var-expr\": {\n            \"name\": \"meta.var.expr.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(var|let|const(?!\\\\s+enum\\\\b))\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.js\"\n                }\n            },\n            \"end\": \"(?=$|^|;|}|(\\\\s+(of|in)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#destructuring-variable\"\n                },\n                {\n                    \"include\": \"#var-single-variable\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(,)\\\\s*(?!\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.comma.js\"\n                        }\n                    },\n                    \"end\": \"(?<!,)((?==|;|}|(\\\\s+(of|in)\\\\s+)|^\\\\s*$))|((?<=\\\\S)(?=\\\\s*$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#destructuring-variable\"\n                        },\n                        {\n                            \"include\": \"#var-single-variable\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"var-single-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.var-single-variable.expr.js\",\n                    \"begin\":\n                        \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.js entity.name.function.js\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.js\",\n                    \"begin\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.js variable.other.constant.js\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.js\",\n                    \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.js variable.other.readwrite.js\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"var-single-variable-type-annotation\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"destructuring-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.object-binding-pattern-variable.js\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\{)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.array-binding-pattern-variable.js\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\[)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"object-binding-element-propertyName\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.destructuring.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"variable.object.property.js\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-variable-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js\"\n                },\n                \"2\": {\n                    \"name\": \"meta.definition.variable.js variable.other.readwrite.js\"\n                }\n            }\n        },\n        \"object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-binding-element\"\n                }\n            ]\n        },\n        \"array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-name\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"\\\\s*\\\\b(public|protected|private|readonly)(?=\\\\s+(public|protected|private|readonly)\\\\s+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:(this)|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.js variable.language.this.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.function.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:((?<!\\\\.|\\\\$)\\\\bthis\\\\b(?!\\\\.|\\\\$))|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.parameter.js variable.language.this.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"variable.parameter.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.js\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"destructuring-parameter\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.parameter.object-binding-pattern.js\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\{)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.js\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-object-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.paramter.array-binding-pattern.js\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\[)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.js\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"parameter-object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#parameter-array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-parameter-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js\"\n                },\n                \"2\": {\n                    \"name\": \"variable.parameter.js\"\n                }\n            }\n        },\n        \"parameter-object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-object-binding-element\"\n                }\n            ]\n        },\n        \"parameter-array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"field-declaration\": {\n            \"name\": \"meta.field.declaration.js\",\n            \"begin\":\n                \"(?<!\\\\()(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s+)?(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js\"\n                }\n            },\n            \"end\":\n                \"(?=\\\\}|;|,|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n                    \"end\":\n                        \"(?=[};,=]|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        },\n                        {\n                            \"include\": \"#array-literal\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.js entity.name.function.js\",\n                            \"match\":\n                                \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\\\?\\\\s*)?\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.js variable.object.property.js\",\n                            \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.optional.js\",\n                            \"match\": \"\\\\?\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"variable-initializer\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.js\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[,);}\\\\]])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.js\"\n                        }\n                    },\n                    \"end\": \"(?=[,);}\\\\]])|(?=^\\\\s*$)|(?<=\\\\S)(?<!=)(?=\\\\s*$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"function-declaration\": {\n            \"name\": \"meta.function.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.async.js\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.function.js\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.generator.asterisk.js\"\n                },\n                \"5\": {\n                    \"name\": \"meta.definition.function.js entity.name.function.js\"\n                }\n            },\n            \"end\": \"(?=$|^|;)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-expression\": {\n            \"name\": \"meta.function.expression.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.function.js\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.js\"\n                },\n                \"4\": {\n                    \"name\": \"meta.definition.function.js entity.name.function.js\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-body\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                },\n                {\n                    \"include\": \"#return-type\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"method-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.method.declaration.js\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.property.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.generator.asterisk.js\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.method.declaration.js\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:(?:\\\\b(?:(new)|(constructor))\\\\b(?!\\\\$|\\\\.|:))|(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))?\\\\s*[\\\\(\\\\<]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.new.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"storage.type.js\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.generator.asterisk.js\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-literal-method-declaration\": {\n            \"name\": \"meta.method.declaration.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.property.js\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.js\"\n                }\n            },\n            \"end\": \"(?=\\\\}|;|,)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#method-declaration-name\"\n                },\n                {\n                    \"include\": \"#function-body\"\n                },\n                {\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.property.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.generator.asterisk.js\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\(|\\\\<)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"method-declaration-name\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??)\\\\s*[\\\\(\\\\<])\",\n            \"end\": \"(?=\\\\(|\\\\<)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"meta.definition.method.js entity.name.function.js\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                },\n                {\n                    \"name\": \"keyword.operator.optional.js\",\n                    \"match\": \"\\\\?\"\n                }\n            ]\n        },\n        \"arrow-function\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.arrow.js\",\n                    \"match\":\n                        \"(?:(?<!\\\\.|\\\\$)(\\\\basync)\\\\s+)?([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?==>)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.parameter.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.arrow.js\",\n                    \"begin\":\n                        \"(?x) (?:\\n  (?<!\\\\.|\\\\$)(\\\\basync)\\n)? ((?<![})!\\\\]])\\\\s*\\n  (?=\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  )\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.js\"\n                        }\n                    },\n                    \"end\":\n                        \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameters\"\n                        },\n                        {\n                            \"include\": \"#function-parameters\"\n                        },\n                        {\n                            \"include\": \"#arrow-return-type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.arrow.js\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.js\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\}|\\\\S)(?<!=>)|((?!\\\\{)(?=\\\\S))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#decl-block\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"indexer-declaration\": {\n            \"name\": \"meta.indexer.declaration.js\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.js\"\n                },\n                \"3\": {\n                    \"name\": \"variable.parameter.js\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.js\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                }\n            ]\n        },\n        \"indexer-mapped-type-declaration\": {\n            \"name\": \"meta.indexer.mappedtype.declaration.js\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s+(in)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.js\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.js\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.operator.expression.in.js\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.js\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"function-parameters\": {\n            \"name\": \"meta.parameters.js\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.begin.js\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter\"\n                },\n                {\n                    \"include\": \"#parameter-name\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"name\": \"punctuation.separator.parameter.js\",\n                    \"match\": \",\"\n                }\n            ]\n        },\n        \"class-declaration\": {\n            \"name\": \"meta.class.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(class)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.js\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.class.js\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-expression\": {\n            \"name\": \"meta.class.js\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(class)\\\\b(?=\\\\s+|[<{]|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.class.js\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-declaration-or-expression-patterns\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.class.js\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"interface-declaration\": {\n            \"name\": \"meta.interface.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(interface)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.js\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.interface.js\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.interface.js\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"class-or-interface-heritage\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:\\\\b(extends|implements)\\\\b)(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js\"\n                }\n            },\n            \"end\": \"(?=\\\\{)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)(?=\\\\s*[_$[:alpha:]][_$[:alnum:]]*(\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)*\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.inherited-class.js\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"class-or-interface-body\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#access-modifier\"\n                },\n                {\n                    \"include\": \"#property-accessor\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"access-modifier\": {\n            \"name\": \"storage.modifier.js\",\n            \"match\":\n                \"(?<!\\\\.|\\\\$)\\\\b(abstract|public|protected|private|readonly|static)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"property-accessor\": {\n            \"name\": \"storage.type.property.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(get|set)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"enum-declaration\": {\n            \"name\": \"meta.enum.declaration.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?(?:\\\\b(const)\\\\s+)?\\\\b(enum)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.js\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.enum.js\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.type.enum.js\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.js\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"variable.other.enummember.js\"\n                                }\n                            },\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\":\n                                \"(?=((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\])))\",\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#string\"\n                                },\n                                {\n                                    \"include\": \"#array-literal\"\n                                },\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"namespace-declaration\": {\n            \"name\": \"meta.namespace.declaration.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(namespace|module)\\\\s+(?=[_$[:alpha:]\\\"'`])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.namespace.js\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\})|(?=;|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"name\": \"entity.name.type.module.js\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"type-alias-declaration\": {\n            \"name\": \"meta.type.declaration.js\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(type)\\\\b\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.type.js\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.alias.js\"\n                }\n            },\n            \"end\":\n                \"(?=[};]|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"match\": \"(=)\\\\s*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.js\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"import-equals-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.import-equals.external.js\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(require)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.control.require.js\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.brace.round.js\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.import-equals.internal.js\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(?!require\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.js\"\n                        }\n                    },\n                    \"end\": \"(?=;|$|^)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"entity.name.type.module.js\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.accessor.js\"\n                                }\n                            }\n                        },\n                        {\n                            \"name\": \"variable.other.readwrite.js\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-declaration\": {\n            \"name\": \"meta.import.js\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)(?!(\\\\s*[:\\\\(])|(\\\\$|\\\\.))\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.js\"\n                }\n            },\n            \"end\": \"(?=;|$|^)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-declaration\"\n                }\n            ]\n        },\n        \"export-declaration\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(export)\\\\s+(as)\\\\s+(namespace)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.as.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.namespace.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.module.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.export.default.js\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?:(?:\\\\s*(=))|(?:\\\\s+(default)(?=\\\\s+)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.assignment.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.default.js\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.export.js\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?!(\\\\s*:)|(\\\\$))\\\\b\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.export.js\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#import-export-declaration\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-export-declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#import-export-block\"\n                },\n                {\n                    \"name\": \"keyword.control.from.js\",\n                    \"match\": \"\\\\bfrom\\\\b\"\n                },\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-block\": {\n            \"name\": \"meta.block.js\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-clause\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bdefault)|(\\\\*)|(\\\\b[_$[:alpha:]][_$[:alnum:]]*))\\\\s+(as)\\\\s+(\\\\b[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.default.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.language.import-export-all.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.control.as.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"variable.other.readwrite.alias.js\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"name\": \"constant.language.import-export-all.js\",\n                    \"match\": \"\\\\*\"\n                },\n                {\n                    \"name\": \"keyword.control.default.js\",\n                    \"match\": \"\\\\b(default)\\\\b\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.alias.js\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"switch-statement\": {\n            \"name\": \"switch-statement.expr.js\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?=\\\\bswitch\\\\s*\\\\()\",\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"switch-expression.expr.js\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(switch)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.switch.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.brace.round.js\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"switch-block.expr.js\",\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.js\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"case-clause.expr.js\",\n                            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(case|default(?=:))\\\\b(?!\\\\$|\\\\.)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.control.switch.js\"\n                                }\n                            },\n                            \"end\": \":\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.section.case-statement.js\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#expression\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#statements\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"for-loop\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(for)(?:\\\\s+(await))?\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.js\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.loop.js\"\n                },\n                \"3\": {\n                    \"name\": \"meta.brace.round.js\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"decl-block\": {\n            \"name\": \"meta.block.js\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#statements\"\n                }\n            ]\n        },\n        \"after-operator-block-as-object-literal\": {\n            \"name\": \"meta.objectliteral.js\",\n            \"begin\":\n                \"(?<=[=(,\\\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\\\|\\\\||\\\\*)\\\\s*(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-literal\": {\n            \"name\": \"meta.objectliteral.js\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-member\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-literal-method-declaration\"\n                },\n                {\n                    \"name\": \"meta.object.member.js meta.object-literal.key.js\",\n                    \"begin\": \"(?=\\\\[)\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-literal\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js meta.object-literal.key.js\",\n                    \"begin\": \"(?=[\\\\'\\\\\\\"])\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"match\": \"(?![_$[:alpha:]])([[:digit:]]+)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js\"\n                        },\n                        \"1\": {\n                            \"name\": \"constant.numeric.decimal.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"match\":\n                        \"(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js\"\n                        },\n                        \"1\": {\n                            \"name\": \"entity.name.function.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"match\": \"(?:[_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.js\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=,|\\\\}|$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.readwrite.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"begin\": \"(?=[_$[:alpha:]][_$[:alnum:]]*\\\\s*=)\",\n                    \"end\": \"(?=,|\\\\}|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js\",\n                    \"begin\": \":\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js punctuation.separator.key-value.js\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"ternary-expression\": {\n            \"begin\": \"(\\\\?)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.js\"\n                }\n            },\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"function-call\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"end\":\n                \"(?<=\\\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.function-call.js\",\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))\",\n                    \"end\":\n                        \"(?=\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#literal\"\n                        },\n                        {\n                            \"include\": \"#support-objects\"\n                        },\n                        {\n                            \"include\": \"#object-identifiers\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.expression.import.js\",\n                            \"match\": \"(?![\\\\.\\\\$])\\\\bimport(?=\\\\s*[\\\\(]\\\\s*[\\\\\\\"\\\\'\\\\`])\"\n                        },\n                        {\n                            \"name\": \"entity.name.function.js\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"meta.type.parameters.js\",\n                    \"begin\": \"\\\\<\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.begin.js\"\n                        }\n                    },\n                    \"end\": \"\\\\>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.end.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                }\n            ]\n        },\n        \"new-expr\": {\n            \"name\": \"new.expr.js\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.new.js\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\))|(?=[;),}\\\\]]|$|((?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.))|((?<!\\\\.|\\\\$)\\\\bfunction((\\\\s+[_$[:alpha:]][_$[:alnum:]]*)|(\\\\s*[\\\\(]))))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"paren-expression\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"cast\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx\"\n                }\n            ]\n        },\n        \"expression-operators\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.flow.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(await)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(yield)\\\\b(?!\\\\$|\\\\.)(?:\\\\s*(\\\\*))?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.flow.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.generator.asterisk.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"keyword.operator.expression.delete.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bdelete\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.in.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bin\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.of.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.instanceof.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\binstanceof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.new.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.void.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bvoid\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(as)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.as.js\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,:})\\\\]]|((?<!\\\\.|\\\\$)\\\\b(as)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"keyword.operator.spread.js\",\n                    \"match\": \"\\\\.\\\\.\\\\.\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.js\",\n                    \"match\": \"\\\\*=|(?<!\\\\()/=|%=|\\\\+=|\\\\-=\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.bitwise.js\",\n                    \"match\": \"\\\\&=|\\\\^=|<<=|>>=|>>>=|\\\\|=\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.shift.js\",\n                    \"match\": \"<<|>>>|>>\"\n                },\n                {\n                    \"name\": \"keyword.operator.comparison.js\",\n                    \"match\": \"===|!==|==|!=\"\n                },\n                {\n                    \"name\": \"keyword.operator.relational.js\",\n                    \"match\": \"<=|>=|<>|<|>\"\n                },\n                {\n                    \"name\": \"keyword.operator.logical.js\",\n                    \"match\": \"\\\\!|&&|\\\\|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.js\",\n                    \"match\": \"\\\\&|~|\\\\^|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.js\",\n                    \"match\": \"\\\\=\"\n                },\n                {\n                    \"name\": \"keyword.operator.decrement.js\",\n                    \"match\": \"--\"\n                },\n                {\n                    \"name\": \"keyword.operator.increment.js\",\n                    \"match\": \"\\\\+\\\\+\"\n                },\n                {\n                    \"name\": \"keyword.operator.arithmetic.js\",\n                    \"match\": \"%|\\\\*|/|-|\\\\+\"\n                },\n                {\n                    \"match\": \"(?<=[_$[:alnum:])])\\\\s*(/)(?![/*])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.arithmetic.js\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"typeof-operator\": {\n            \"name\": \"keyword.operator.expression.typeof.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\btypeof\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#boolean-literal\"\n                },\n                {\n                    \"include\": \"#null-literal\"\n                },\n                {\n                    \"include\": \"#undefined-literal\"\n                },\n                {\n                    \"include\": \"#numericConstant-literal\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"include\": \"#this-literal\"\n                },\n                {\n                    \"include\": \"#super-literal\"\n                }\n            ]\n        },\n        \"array-literal\": {\n            \"name\": \"meta.array.literal.js\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"numeric-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.numeric.hex.js\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(x|X)[0-9a-fA-F]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.binary.js\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(b|B)[01]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.octal.js\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(o|O)?[0-7]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(?<!\\\\$)(?:\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)| # 1.1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[eE][+-]?[0-9]+\\\\b)|       # 1.E+3\\n  (?:\\\\B(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)|       # .1E+3\\n  (?:\\\\b[0-9]+[eE][+-]?[0-9]+\\\\b)|           # 1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+\\\\b)|                # 1.1\\n  (?:\\\\b[0-9]+(\\\\.)\\\\B)|                      # 1.\\n  (?:\\\\B(\\\\.)[0-9]+\\\\b)|                      # .1\\n  (?:\\\\b[0-9]+\\\\b(?!\\\\.))                     # 1\\n)(?!\\\\$)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"constant.numeric.decimal.js\"\n                        },\n                        \"1\": {\n                            \"name\": \"meta.delimiter.decimal.period.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.delimiter.decimal.period.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.delimiter.decimal.period.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.delimiter.decimal.period.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"meta.delimiter.decimal.period.js\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.delimiter.decimal.period.js\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"boolean-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.boolean.true.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\btrue\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.boolean.false.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bfalse\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"null-literal\": {\n            \"name\": \"constant.language.null.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bnull\\\\b(?!\\\\$)\"\n        },\n        \"this-literal\": {\n            \"name\": \"variable.language.this.js\",\n            \"match\": \"(?<!\\\\$)((?<=\\\\.\\\\.\\\\.)|(?<!\\\\.))\\\\bthis\\\\b(?!\\\\$)\"\n        },\n        \"super-literal\": {\n            \"name\": \"variable.language.super.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bsuper\\\\b(?!\\\\$)\"\n        },\n        \"undefined-literal\": {\n            \"name\": \"constant.language.undefined.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bundefined\\\\b(?!\\\\$)\"\n        },\n        \"numericConstant-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.nan.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bNaN\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.infinity.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bInfinity\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"support-objects\": {\n            \"patterns\": [\n                {\n                    \"name\": \"variable.language.arguments.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(arguments)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.builtin.js\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Array|ArrayBuffer|Atomics|Boolean|DataView|Date|Float32Array|Float64Array|Function|Generator\\n  |GeneratorFunction|Int8Array|Int16Array|Int32Array|Intl|Map|Number|Object|Promise|Proxy\\n  |Reflect|RegExp|Set|SharedArrayBuffer|SIMD|String|Symbol|TypedArray\\n  |Uint8Array|Uint16Array|Uint32Array|Uint8ClampedArray|WeakMap|WeakSet)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.error.js\",\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b((Eval|Internal|Range|Reference|Syntax|Type|URI)?Error)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.function.js\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(clear(Interval|Timeout)|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|\\n  isFinite|isNaN|parseFloat|parseInt|require|set(Interval|Timeout)|super|unescape|uneval)(?=\\\\s*\\\\()\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Math)(?:\\\\s*(\\\\.)\\\\s*(?:\\n  (abs|acos|acosh|asin|asinh|atan|atan2|atanh|cbrt|ceil|clz32|cos|cosh|exp|\\n  expm1|floor|fround|hypot|imul|log|log10|log1p|log2|max|min|pow|random|\\n  round|sign|sin|sinh|sqrt|tan|tanh|trunc)\\n  |\\n  (E|LN10|LN2|LOG10E|LOG2E|PI|SQRT1_2|SQRT2)))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.math.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.math.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.constant.property.math.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(console)(?:\\\\s*(\\\\.)\\\\s*(\\n  assert|clear|count|debug|dir|error|group|groupCollapsed|groupEnd|info|log\\n  |profile|profileEnd|table|time|timeEnd|timeStamp|trace|warn))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.class.console.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.console.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(JSON)(?:\\\\s*(\\\\.)\\\\s*(parse|stringify))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.json.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.json.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (constructor|length|prototype|__proto__)\\n  |\\n  (EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.variable.property.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.constant.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (?<!\\\\.|\\\\$) \\\\b (?:\\n  (document|event|navigator|performance|screen|window)\\n  |\\n  (AnalyserNode|ArrayBufferView|Attr|AudioBuffer|AudioBufferSourceNode|AudioContext|AudioDestinationNode|AudioListener\\n  |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule\\n  |CSSCounterStyleRule|CSSGroupingRule|CSSMatrix|CSSMediaRule|CSSPageRule|CSSPrimitiveValue|CSSRule|CSSRuleList|CSSStyleDeclaration\\n  |CSSStyleRule|CSSStyleSheet|CSSSupportsRule|CSSValue|CSSValueList|CanvasGradient|CanvasImageSource|CanvasPattern\\n  |CanvasRenderingContext2D|ChannelMergerNode|ChannelSplitterNode|CharacterData|ChromeWorker|CloseEvent|Comment|CompositionEvent\\n  |Console|ConvolverNode|Coordinates|Credential|CredentialsContainer|Crypto|CryptoKey|CustomEvent|DOMError|DOMException\\n  |DOMHighResTimeStamp|DOMImplementation|DOMString|DOMStringList|DOMStringMap|DOMTimeStamp|DOMTokenList|DataTransfer\\n  |DataTransferItem|DataTransferItemList|DedicatedWorkerGlobalScope|DelayNode|DeviceProximityEvent|DirectoryEntry\\n  |DirectoryEntrySync|DirectoryReader|DirectoryReaderSync|Document|DocumentFragment|DocumentTouch|DocumentType|DragEvent\\n  |DynamicsCompressorNode|Element|Entry|EntrySync|ErrorEvent|Event|EventListener|EventSource|EventTarget|FederatedCredential\\n  |FetchEvent|File|FileEntry|FileEntrySync|FileException|FileList|FileReader|FileReaderSync|FileSystem|FileSystemSync\\n  |FontFace|FormData|GainNode|Gamepad|GamepadButton|GamepadEvent|Geolocation|GlobalEventHandlers|HTMLAnchorElement\\n  |HTMLAreaElement|HTMLAudioElement|HTMLBRElement|HTMLBaseElement|HTMLBodyElement|HTMLButtonElement|HTMLCanvasElement\\n  |HTMLCollection|HTMLContentElement|HTMLDListElement|HTMLDataElement|HTMLDataListElement|HTMLDialogElement|HTMLDivElement\\n  |HTMLDocument|HTMLElement|HTMLEmbedElement|HTMLFieldSetElement|HTMLFontElement|HTMLFormControlsCollection|HTMLFormElement\\n  |HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLIFrameElement|HTMLImageElement|HTMLInputElement\\n  |HTMLKeygenElement|HTMLLIElement|HTMLLabelElement|HTMLLegendElement|HTMLLinkElement|HTMLMapElement|HTMLMediaElement\\n  |HTMLMetaElement|HTMLMeterElement|HTMLModElement|HTMLOListElement|HTMLObjectElement|HTMLOptGroupElement|HTMLOptionElement\\n  |HTMLOptionsCollection|HTMLOutputElement|HTMLParagraphElement|HTMLParamElement|HTMLPreElement|HTMLProgressElement\\n  |HTMLQuoteElement|HTMLScriptElement|HTMLSelectElement|HTMLShadowElement|HTMLSourceElement|HTMLSpanElement|HTMLStyleElement\\n  |HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement\\n  |HTMLTableRowElement|HTMLTableSectionElement|HTMLTextAreaElement|HTMLTimeElement|HTMLTitleElement|HTMLTrackElement\\n  |HTMLUListElement|HTMLUnknownElement|HTMLVideoElement|HashChangeEvent|History|IDBCursor|IDBCursorWithValue|IDBDatabase\\n  |IDBEnvironment|IDBFactory|IDBIndex|IDBKeyRange|IDBMutableFile|IDBObjectStore|IDBOpenDBRequest|IDBRequest|IDBTransaction\\n  |IDBVersionChangeEvent|IIRFilterNode|IdentityManager|ImageBitmap|ImageBitmapFactories|ImageData|Index|InputDeviceCapabilities\\n  |InputEvent|InstallEvent|InstallTrigger|KeyboardEvent|LinkStyle|LocalFileSystem|LocalFileSystemSync|Location|MIDIAccess\\n  |MIDIConnectionEvent|MIDIInput|MIDIInputMap|MIDIOutputMap|MediaElementAudioSourceNode|MediaError|MediaKeyMessageEvent\\n  |MediaKeySession|MediaKeyStatusMap|MediaKeySystemAccess|MediaKeySystemConfiguration|MediaKeys|MediaRecorder|MediaStream\\n  |MediaStreamAudioDestinationNode|MediaStreamAudioSourceNode|MessageChannel|MessageEvent|MessagePort|MouseEvent\\n  |MutationObserver|MutationRecord|NamedNodeMap|Navigator|NavigatorConcurrentHardware|NavigatorGeolocation|NavigatorID\\n  |NavigatorLanguage|NavigatorOnLine|Node|NodeFilter|NodeIterator|NodeList|NonDocumentTypeChildNode|Notification\\n  |OfflineAudioCompletionEvent|OfflineAudioContext|OscillatorNode|PageTransitionEvent|PannerNode|ParentNode|PasswordCredential\\n  |Path2D|PaymentAddress|PaymentRequest|PaymentResponse|Performance|PerformanceEntry|PerformanceFrameTiming|PerformanceMark\\n  |PerformanceMeasure|PerformanceNavigation|PerformanceNavigationTiming|PerformanceObserver|PerformanceObserverEntryList\\n  |PerformanceResourceTiming|PerformanceTiming|PeriodicSyncEvent|PeriodicWave|Plugin|Point|PointerEvent|PopStateEvent\\n  |PortCollection|Position|PositionError|PositionOptions|PresentationConnectionClosedEvent|PresentationConnectionList\\n  |PresentationReceiver|ProcessingInstruction|ProgressEvent|PromiseRejectionEvent|PushEvent|PushRegistrationManager\\n  |RTCCertificate|RTCConfiguration|RTCPeerConnection|RTCSessionDescriptionCallback|RTCStatsReport|RadioNodeList|RandomSource\\n  |Range|ReadableByteStream|RenderingContext|SVGAElement|SVGAngle|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement\\n  |SVGAnimateTransformElement|SVGAnimatedAngle|SVGAnimatedBoolean|SVGAnimatedEnumeration|SVGAnimatedInteger|SVGAnimatedLength\\n  |SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedPoints|SVGAnimatedPreserveAspectRatio\\n  |SVGAnimatedRect|SVGAnimatedString|SVGAnimatedTransformList|SVGAnimationElement|SVGCircleElement|SVGClipPathElement\\n  |SVGCursorElement|SVGDefsElement|SVGDescElement|SVGElement|SVGEllipseElement|SVGEvent|SVGFilterElement|SVGFontElement\\n  |SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement\\n  |SVGForeignObjectElement|SVGGElement|SVGGlyphElement|SVGGradientElement|SVGHKernElement|SVGImageElement|SVGLength\\n  |SVGLengthList|SVGLineElement|SVGLinearGradientElement|SVGMPathElement|SVGMaskElement|SVGMatrix|SVGMissingGlyphElement\\n  |SVGNumber|SVGNumberList|SVGPathElement|SVGPatternElement|SVGPoint|SVGPolygonElement|SVGPolylineElement|SVGPreserveAspectRatio\\n  |SVGRadialGradientElement|SVGRect|SVGRectElement|SVGSVGElement|SVGScriptElement|SVGSetElement|SVGStopElement|SVGStringList\\n  |SVGStylable|SVGStyleElement|SVGSwitchElement|SVGSymbolElement|SVGTRefElement|SVGTSpanElement|SVGTests|SVGTextElement\\n  |SVGTextPositioningElement|SVGTitleElement|SVGTransform|SVGTransformList|SVGTransformable|SVGUseElement|SVGVKernElement\\n  |SVGViewElement|ServiceWorker|ServiceWorkerContainer|ServiceWorkerGlobalScope|ServiceWorkerRegistration|ServiceWorkerState\\n  |ShadowRoot|SharedWorker|SharedWorkerGlobalScope|SourceBufferList|StereoPannerNode|Storage|StorageEvent|StyleSheet\\n  |StyleSheetList|SubtleCrypto|SyncEvent|Text|TextMetrics|TimeEvent|TimeRanges|Touch|TouchEvent|TouchList|Transferable\\n  |TreeWalker|UIEvent|USVString|VRDisplayCapabilities|ValidityState|WaveShaperNode|WebGL|WebGLActiveInfo|WebGLBuffer\\n  |WebGLContextEvent|WebGLFramebuffer|WebGLProgram|WebGLRenderbuffer|WebGLRenderingContext|WebGLShader|WebGLShaderPrecisionFormat\\n  |WebGLTexture|WebGLTimerQueryEXT|WebGLTransformFeedback|WebGLUniformLocation|WebGLVertexArrayObject|WebGLVertexArrayObjectOES\\n  |WebSocket|WebSockets|WebVTT|WheelEvent|Window|WindowBase64|WindowEventHandlers|WindowTimers|Worker|WorkerGlobalScope\\n  |WorkerLocation|WorkerNavigator|XMLHttpRequest|XMLHttpRequestEventTarget|XMLSerializer|XPathExpression|XPathResult\\n  |XSLTProcessor))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.dom.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.class.dom.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\\n  |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\\n  |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\\n  |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\\n  |\\n  (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\\n  |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\\n  |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\\n  |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\\n  |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\\n  |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\\n  |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\\n  |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\\n  |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\\n  |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\\n  |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\\n  |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\\n  |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\\n  |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\\n  |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\\n  |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\\n  |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\\n  |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\\n  |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\\n  |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\\n  |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\\n  |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\\n  |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\\n  |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\\n  |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\\n  |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\\\b(?!\\\\$|\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.constant.dom.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.dom.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.class.node.js\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Buffer|EventEmitter|Server|Pipe|Socket|REPLServer|ReadStream|WriteStream|Stream\\n  |Inflate|Deflate|InflateRaw|DeflateRaw|GZip|GUnzip|Unzip|Zip)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(process)(?:(\\\\.)(?:\\n  (arch|argv|config|connected|env|execArgv|execPath|exitCode|mainModule|pid|platform|release|stderr|stdin|stdout|title|version|versions)\\n  |\\n  (abort|chdir|cwd|disconnect|exit|[sg]ete?[gu]id|send|[sg]etgroups|initgroups|kill|memoryUsage|nextTick|umask|uptime|hrtime)\\n))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.object.process.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.process.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.process.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(?:(exports)|(module)(?:(\\\\.)(exports|id|filename|loaded|parent|children))?)\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.type.object.module.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.type.object.module.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.type.object.module.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.variable.object.node.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(global|GLOBAL|root|__dirname|__filename)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s*\\n(?:\\n (on(?:Rowsinserted|Rowsdelete|Rowenter|Rowexit|Resize|Resizestart|Resizeend|Reset|\\n   Readystatechange|Mouseout|Mouseover|Mousedown|Mouseup|Mousemove|\\n   Before(?:cut|deactivate|unload|update|paste|print|editfocus|activate)|\\n   Blur|Scrolltop|Submit|Select|Selectstart|Selectionchange|Hover|Help|\\n   Change|Contextmenu|Controlselect|Cut|Cellchange|Clock|Close|Deactivate|\\n   Datasetchanged|Datasetcomplete|Dataavailable|Drop|Drag|Dragstart|Dragover|\\n   Dragdrop|Dragenter|Dragend|Dragleave|Dblclick|Unload|Paste|Propertychange|Error|\\n   Errorupdate|Keydown|Keyup|Keypress|Focus|Load|Activate|Afterupdate|Afterprint|Abort)\\n ) |\\n (shift|showModelessDialog|showModalDialog|showHelp|scroll|scrollX|scrollByPages|\\n   scrollByLines|scrollY|scrollTo|stop|strike|sizeToContent|sidebar|signText|sort|\\n   sup|sub|substr|substring|splice|split|send|set(?:Milliseconds|Seconds|Minutes|Hours|\\n   Month|Year|FullYear|Date|UTC(?:Milliseconds|Seconds|Minutes|Hours|Month|FullYear|Date)|\\n   Time|Hotkeys|Cursor|ZOptions|Active|Resizable|RequestHeader)|search|slice|\\n   savePreferences|small|home|handleEvent|navigate|char|charCodeAt|charAt|concat|\\n   contextual|confirm|compile|clear|captureEvents|call|createStyleSheet|createPopup|\\n   createEventObject|to(?:GMTString|UTCString|String|Source|UpperCase|LowerCase|LocaleString)|\\n   test|taint|taintEnabled|indexOf|italics|disableExternalCapture|dump|detachEvent|unshift|\\n   untaint|unwatch|updateCommands|join|javaEnabled|pop|push|plugins.refresh|paddings|parse|\\n   print|prompt|preference|enableExternalCapture|exec|execScript|valueOf|UTC|find|file|\\n   fileModifiedDate|fileSize|fileCreatedDate|fileUpdatedDate|fixed|fontsize|fontcolor|\\n   forward|fromCharCode|watch|link|load|lastIndexOf|anchor|attachEvent|atob|apply|alert|\\n   abort|routeEvents|resize|resizeBy|resizeTo|recalc|returnValue|replace|reverse|reload|\\n   releaseCapture|releaseEvents|go|get(?:Milliseconds|Seconds|Minutes|Hours|Month|Day|Year|FullYear|\\n   Time|Date|TimezoneOffset|UTC(?:Milliseconds|Seconds|Minutes|Hours|Day|Month|FullYear|Date)|\\n   Attention|Selection|ResponseHeader|AllResponseHeaders)|moveBy|moveBelow|moveTo|\\n   moveToAbsolute|moveAbove|mergeAttributes|match|margins|btoa|big|bold|borderWidths|blink|back\\n ) |\\n (acceptNode|add|addEventListener|addTextTrack|adoptNode|after|animate|append|\\n   appendChild|appendData|before|blur|canPlayType|captureStream|\\n   caretPositionFromPoint|caretRangeFromPoint|checkValidity|clear|click|\\n   cloneContents|cloneNode|cloneRange|close|closest|collapse|\\n   compareBoundaryPoints|compareDocumentPosition|comparePoint|contains|\\n   convertPointFromNode|convertQuadFromNode|convertRectFromNode|createAttribute|\\n   createAttributeNS|createCaption|createCDATASection|createComment|\\n   createContextualFragment|createDocument|createDocumentFragment|\\n   createDocumentType|createElement|createElementNS|createEntityReference|\\n   createEvent|createExpression|createHTMLDocument|createNodeIterator|\\n   createNSResolver|createProcessingInstruction|createRange|createShadowRoot|\\n   createTBody|createTextNode|createTFoot|createTHead|createTreeWalker|delete|\\n   deleteCaption|deleteCell|deleteContents|deleteData|deleteRow|deleteTFoot|\\n   deleteTHead|detach|disconnect|dispatchEvent|elementFromPoint|elementsFromPoint|\\n   enableStyleSheetsForSet|entries|evaluate|execCommand|exitFullscreen|\\n   exitPointerLock|expand|extractContents|fastSeek|firstChild|focus|forEach|get|\\n   getAll|getAnimations|getAttribute|getAttributeNames|getAttributeNode|\\n   getAttributeNodeNS|getAttributeNS|getBoundingClientRect|getBoxQuads|\\n   getClientRects|getContext|getDestinationInsertionPoints|getElementById|\\n   getElementsByClassName|getElementsByName|getElementsByTagName|\\n   getElementsByTagNameNS|getItem|getNamedItem|getSelection|getStartDate|\\n   getVideoPlaybackQuality|has|hasAttribute|hasAttributeNS|hasAttributes|\\n   hasChildNodes|hasFeature|hasFocus|importNode|initEvent|insertAdjacentElement|\\n   insertAdjacentHTML|insertAdjacentText|insertBefore|insertCell|insertData|\\n   insertNode|insertRow|intersectsNode|isDefaultNamespace|isEqualNode|\\n   isPointInRange|isSameNode|item|key|keys|lastChild|load|lookupNamespaceURI|\\n   lookupPrefix|matches|move|moveAttribute|moveAttributeNode|moveChild|\\n   moveNamedItem|namedItem|nextNode|nextSibling|normalize|observe|open|\\n   parentNode|pause|play|postMessage|prepend|preventDefault|previousNode|\\n   previousSibling|probablySupportsContext|queryCommandEnabled|\\n   queryCommandIndeterm|queryCommandState|queryCommandSupported|queryCommandValue|\\n   querySelector|querySelectorAll|registerContentHandler|registerElement|\\n   registerProtocolHandler|releaseCapture|releaseEvents|remove|removeAttribute|\\n   removeAttributeNode|removeAttributeNS|removeChild|removeEventListener|\\n   removeItem|replace|replaceChild|replaceData|replaceWith|reportValidity|\\n   requestFullscreen|requestPointerLock|reset|scroll|scrollBy|scrollIntoView|\\n   scrollTo|seekToNextFrame|select|selectNode|selectNodeContents|set|setAttribute|\\n   setAttributeNode|setAttributeNodeNS|setAttributeNS|setCapture|\\n   setCustomValidity|setEnd|setEndAfter|setEndBefore|setItem|setNamedItem|\\n   setRangeText|setSelectionRange|setSinkId|setStart|setStartAfter|setStartBefore|\\n   slice|splitText|stepDown|stepUp|stopImmediatePropagation|stopPropagation|\\n   submit|substringData|supports|surroundContents|takeRecords|terminate|toBlob|\\n   toDataURL|toggle|toString|values|write|writeln\\n )\\n)(?=\\\\s*\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.function.event-handler.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.dom.js\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"identifiers\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#object-identifiers\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:(\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.property.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.property.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"variable.other.constant.js\",\n                    \"match\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.js\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"object-identifiers\": {\n            \"patterns\": [\n                {\n                    \"name\": \"support.class.js\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\\\.\\\\s*prototype\\\\b(?!\\\\$))\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(\\\\.)\\\\s*(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.object.property.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.object.property.js\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.constant.object.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.object.js\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"type-annotation\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.annotation.js\",\n                    \"begin\": \"(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=$|^|[,);\\\\}\\\\]]|//)|(?==[^>])|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.annotation.js\",\n                    \"begin\": \"(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=[,);\\\\}\\\\]]|//)|(?==[^>])|(?=^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$))|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.return.type.js\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])(?=$|^|[{};,]|//)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.return.type.js\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])((?=[{};,]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<=[:|&])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"arrow-return-type\": {\n            \"name\": \"meta.return.type.arrow.js\",\n            \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.type.annotation.js\"\n                }\n            },\n            \"end\":\n                \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=[:])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-parameters\": {\n            \"name\": \"meta.type.parameters.js\",\n            \"begin\": \"(<)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.begin.js\"\n                }\n            },\n            \"end\": \"(>)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"storage.modifier.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(extends)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.js\",\n                    \"match\": \"\\\\=(?!>)\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#type-primitive\"\n                },\n                {\n                    \"include\": \"#type-builtin-literals\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type-tuple\"\n                },\n                {\n                    \"include\": \"#type-object\"\n                },\n                {\n                    \"include\": \"#type-operators\"\n                },\n                {\n                    \"include\": \"#type-fn-type-parameters\"\n                },\n                {\n                    \"include\": \"#type-paren-or-function-parameters\"\n                },\n                {\n                    \"include\": \"#type-function-return-type\"\n                },\n                {\n                    \"include\": \"#type-name\"\n                }\n            ]\n        },\n        \"type-primitive\": {\n            \"name\": \"support.type.primitive.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(string|number|boolean|symbol|any|void|never)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-builtin-literals\": {\n            \"name\": \"support.type.builtin.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(this|true|false|undefined|null|object)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-tuple\": {\n            \"name\": \"meta.type.tuple.js\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type-object\": {\n            \"name\": \"meta.object.type.js\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-mapped-type-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.js\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-paren-or-function-parameters\": {\n            \"name\": \"meta.type.paren.cover.js\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                }\n            ]\n        },\n        \"type-fn-type-parameters\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.constructor.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?=\\\\s*\\\\<)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.type.constructor.js\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b\\\\s*(?=\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.js\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.js\",\n                    \"begin\":\n                        \"(?x)(\\n  (?=\\n    [(]\\\\s*(\\n      ([)]) |\\n      (\\\\.\\\\.\\\\.) |\\n      ([_$[:alnum:]]+\\\\s*(\\n        ([:,?=])|\\n        ([)]\\\\s*=>)\\n      ))\\n    )\\n  )\\n)\",\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.function.return.js\",\n                    \"begin\": \"(=>)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.arrow.js\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])(?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.return.js\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.js\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])((?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<==>)(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-operators\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"begin\": \"([&|])(?=\\\\s*\\\\{)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.js\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"[&|]\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.js\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\S)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.keyof.js\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bkeyof\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"type-predicate-operator\": {\n            \"name\": \"keyword.operator.expression.is.js\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bis\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-name\": {\n            \"patterns\": [\n                {\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.js\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"punctuation-comma\": {\n            \"name\": \"punctuation.separator.comma.js\",\n            \"match\": \",\"\n        },\n        \"punctuation-semicolon\": {\n            \"name\": \"punctuation.terminator.statement.js\",\n            \"match\": \";\"\n        },\n        \"punctuation-accessor\": {\n            \"name\": \"punctuation.accessor.js\",\n            \"match\": \"\\\\.\"\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#qstring-single\"\n                },\n                {\n                    \"include\": \"#qstring-double\"\n                }\n            ]\n        },\n        \"qstring-double\": {\n            \"name\": \"string.quoted.double.js\",\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js\"\n                }\n            },\n            \"end\": \"(\\\")|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.js\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"qstring-single\": {\n            \"name\": \"string.quoted.single.js\",\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js\"\n                }\n            },\n            \"end\": \"(\\\\')|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.js\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"string-character-escape\": {\n            \"name\": \"constant.character.escape.js\",\n            \"match\": \"\\\\\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)\"\n        },\n        \"template\": {\n            \"name\": \"string.template.js\",\n            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)?(`)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.tagged-template.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.template.begin.js\"\n                }\n            },\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.template.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#template-substitution-element\"\n                },\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"template-substitution-element\": {\n            \"name\": \"meta.template.expression.js\",\n            \"begin\": \"\\\\$\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.begin.js\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ],\n            \"contentName\": \"meta.embedded.line.js\"\n        },\n        \"regex\": {\n            \"patterns\": [\n                {\n                    \"name\": \"string.regexp.js\",\n                    \"begin\":\n                        \"(?<=[=(:,\\\\[?+!]|return|case|=>|&&|\\\\|\\\\||\\\\*\\\\/)\\\\s*(\\\\/)(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.js\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.regexp.js\",\n                    \"begin\":\n                        \"(?<![_$[:alnum:])])\\\\/(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.js\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"regexp\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.anchor.regexp\",\n                    \"match\": \"\\\\\\\\[bB]|\\\\^|\\\\$\"\n                },\n                {\n                    \"name\": \"keyword.other.back-reference.regexp\",\n                    \"match\": \"\\\\\\\\[1-9]\\\\d*\"\n                },\n                {\n                    \"name\": \"keyword.operator.quantifier.regexp\",\n                    \"match\": \"[?+*]|\\\\{(\\\\d+,\\\\d+|\\\\d+,|,\\\\d+|\\\\d+)\\\\}\\\\??\"\n                },\n                {\n                    \"name\": \"keyword.operator.or.regexp\",\n                    \"match\": \"\\\\|\"\n                },\n                {\n                    \"name\": \"meta.group.assertion.regexp\",\n                    \"begin\": \"(\\\\()((\\\\?=)|(\\\\?!))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.group.assertion.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.assertion.look-ahead.regexp\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.assertion.negative-look-ahead.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.group.regexp\",\n                    \"begin\": \"\\\\((\\\\?:)?\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.no-capture.regexp\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"constant.other.character-class.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"constant.other.character-class.range.regexp\",\n                            \"match\":\n                                \"(?:.|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\\\\-(?:[^\\\\]\\\\\\\\]|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"2\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"3\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                },\n                                \"4\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"5\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"6\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#regex-character-class\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#regex-character-class\"\n                }\n            ]\n        },\n        \"regex-character-class\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.character-class.regexp\",\n                    \"match\": \"\\\\\\\\[wWsSdDtrnvf]|\\\\.\"\n                },\n                {\n                    \"name\": \"constant.character.numeric.regexp\",\n                    \"match\": \"\\\\\\\\([0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})\"\n                },\n                {\n                    \"name\": \"constant.character.control.regexp\",\n                    \"match\": \"\\\\\\\\c[A-Z]\"\n                },\n                {\n                    \"name\": \"constant.character.escape.backslash.regexp\",\n                    \"match\": \"\\\\\\\\.\"\n                }\n            ]\n        },\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.block.documentation.js\",\n                    \"begin\": \"/\\\\*\\\\*(?!/)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.js\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#docblock\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"comment.block.js\",\n                    \"begin\": \"(/\\\\*)(?:\\\\s*((@)internal)(?=\\\\s|(\\\\*/)))?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.internaldeclaration.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.js\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.js\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"comment.line.double-slash.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.comment.js\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.internaldeclaration.js\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.js\"\n                        }\n                    },\n                    \"end\": \"(?=^)\",\n                    \"contentName\": \"comment.line.double-slash.js\"\n                }\n            ]\n        },\n        \"directives\": {\n            \"name\": \"comment.line.triple-slash.directive.js\",\n            \"begin\":\n                \"^(///)\\\\s*(?=<(reference|amd-dependency|amd-module)(\\\\s+(path|types|no-default-lib|name)\\\\s*=\\\\s*((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")))+\\\\s*/>\\\\s*$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.js\"\n                }\n            },\n            \"end\": \"(?=^)\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.tag.js\",\n                    \"begin\": \"(<)(reference|amd-dependency|amd-module)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.directive.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.directive.js\"\n                        }\n                    },\n                    \"end\": \"/>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.tag.directive.js\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"entity.other.attribute-name.directive.js\",\n                            \"match\": \"path|types|no-default-lib|name\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.assignment.js\",\n                            \"match\": \"=\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"docblock\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n((@)(?:access|api))\\n\\\\s+\\n(private|protected|public)\\n\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.access-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)author)\\n\\\\s+\\n(\\n  [^@\\\\s<>*/]\\n  (?:[^@<>*/]|\\\\*[^/])*\\n)\\n(?:\\n  \\\\s*\\n  (<)\\n  ([^>\\\\s]+)\\n  (>)\\n)?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"constant.other.email.link.underline.jsdoc\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)borrows) \\\\s+\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <that namepath>\\n\\\\s+ (as) \\\\s+              # as\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <this namepath>\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.control.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.example.jsdoc\",\n                    \"begin\": \"((@)example)\\\\s+\",\n                    \"end\": \"(?=@|\\\\*/)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"^\\\\s\\\\*\\\\s+\"\n                        },\n                        {\n                            \"contentName\": \"constant.other.description.jsdoc\",\n                            \"begin\": \"\\\\G(<)caption(>)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            },\n                            \"end\": \"(</)caption(>)|(?=\\\\*/)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"[^\\\\s@*](?:[^*]|\\\\*[^/])*\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"source.embedded.js\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x) ((@)kind) \\\\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.symbol-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)see)\\n\\\\s+\\n(?:\\n  # URL\\n  (\\n    (?=https?://)\\n    (?:[^\\\\s*]|\\\\*[^/])+\\n  )\\n  |\\n  # JSDoc namepath\\n  (\\n    (?!\\n      # Avoid matching bare URIs (also acceptable as links)\\n      https?://\\n      |\\n      # Avoid matching {@inline tags}; we match those below\\n      (?:\\\\[[^\\\\[\\\\]]*\\\\])? # Possible description [preceding]{@tag}\\n      {@(?:link|linkcode|linkplain|tutorial)\\\\b\\n    )\\n    # Matched namepath\\n    (?:[^@\\\\s*/]|\\\\*[^/])+\\n  )\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.link.underline.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)template)\\n\\\\s+\\n# One or more valid identifiers\\n(\\n  [A-Za-z_$]         # First character: non-numeric word character\\n  [\\\\w$.\\\\[\\\\]]*        # Rest of identifier\\n  (?:                # Possible list of additional identifiers\\n    \\\\s* , \\\\s*\\n    [A-Za-z_$]\\n    [\\\\w$.\\\\[\\\\]]*\\n  )*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:arg|argument|const|constant|member|namespace|param|var)\\n)\\n\\\\s+\\n(\\n  [A-Za-z_$]\\n  [\\\\w$.\\\\[\\\\]]*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"((@)typedef)\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"entity.name.type.instance.jsdoc\",\n                            \"match\": \"(?:[^@\\\\s*/]|\\\\*[^/])+\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\": \"([A-Za-z_$][\\\\w$.\\\\[\\\\]]*)\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\":\n                                \"(?x)\\n(\\\\[)\\\\s*\\n[\\\\w$]+\\n(?:\\n  (?:\\\\[\\\\])?                                        # Foo[ ].bar properties within an array\\n  \\\\.                                                # Foo.Bar namespaced parameter\\n  [\\\\w$]+\\n)*\\n(?:\\n  \\\\s*\\n  (=)                                                # [foo=bar] Default parameter value\\n  \\\\s*\\n  (\\n    # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\\n    (?>\\n      \\\"(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!\\\"))|[^*\\\\\\\\])*?\\\" |                      # [foo=\\\"bar\\\"] Double-quoted\\n      '(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!'))|[^*\\\\\\\\])*?' |                      # [foo='bar'] Single-quoted\\n      \\\\[ (?:(?:\\\\*(?!/))|[^*])*? \\\\] |                                # [foo=[1,2]] Array literal\\n      (?:(?:\\\\*(?!/))|\\\\s(?!\\\\s*\\\\])|\\\\[.*?(?:\\\\]|(?=\\\\*/))|[^*\\\\s\\\\[\\\\]])*   # Everything else\\n    )*\\n  )\\n)?\\n\\\\s*(?:(\\\\])((?:[^*\\\\s]|\\\\*[^\\\\s/])+)?|(?=\\\\*/))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.begin.bracket.square.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"keyword.operator.assignment.jsdoc\"\n                                },\n                                \"3\": {\n                                    \"name\": \"source.embedded.js\"\n                                },\n                                \"4\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.end.bracket.square.jsdoc\"\n                                },\n                                \"5\": {\n                                    \"name\": \"invalid.illegal.syntax.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:define|enum|exception|export|extends|lends|implements|modifies\\n  |namespace|private|protected|returns?|suppress|this|throws|type\\n  |yields?)\\n)\\n\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:alias|augments|callback|constructs|emits|event|fires|exports?\\n  |extends|external|function|func|host|lends|listens|interface|memberof!?\\n  |method|module|mixes|mixin|name|requires|see|this|typedef|uses)\\n)\\n\\\\s+\\n(\\n  (?:\\n    [^{}@\\\\s*] | \\\\*[^/]\\n  )+\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"contentName\": \"variable.other.jsdoc\",\n                    \"begin\": \"((@)(?:default(?:value)?|license|version))\\\\s+(([''\\\"]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(\\\\3)|(?=$|\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"((@)(?:default(?:value)?|license|tutorial|variation|version))\\\\s+([^\\\\s*]+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"storage.type.class.jsdoc\",\n                    \"match\":\n                        \"(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#inline-tags\"\n                }\n            ]\n        },\n        \"brackets\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\[\",\n                    \"end\": \"\\\\]|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"inline-tags\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.description.jsdoc\",\n                    \"match\": \"(\\\\[)[^\\\\]]+(\\\\])(?={@(?:link|linkcode|linkplain|tutorial))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.square.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.square.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"({)((@)(?:link(?:code|plain)?|tutorial))\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.inline.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\G((?=https?://)(?:[^|}\\\\s*]|\\\\*[/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.link.underline.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"\\\\G((?:[^{}@\\\\s|*]|\\\\*[^/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.description.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsdoctype\": {\n            \"patterns\": [\n                {\n                    \"name\": \"invalid.illegal.type.jsdoc\",\n                    \"match\": \"\\\\G{(?:[^}*]|\\\\*[^/}])+$\"\n                },\n                {\n                    \"contentName\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"\\\\G({)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"((}))\\\\s*|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsx\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes-in-expression\"\n                },\n                {\n                    \"include\": \"#jsx-tag-in-expression\"\n                }\n            ]\n        },\n        \"jsx-tag-without-attributes-in-expression\": {\n            \"begin\":\n                \"(?x)\\n  (?<=[({\\\\[,?=>:*]|&&|\\\\|\\\\||\\\\?|\\\\Wreturn|^return|\\\\Wdefault|^)\\\\s*\\n  (?=(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>))\",\n            \"end\": \"(?!\\\\s*(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes\"\n                }\n            ]\n        },\n        \"jsx-tag-without-attributes\": {\n            \"name\": \"meta.tag.without-attributes.js\",\n            \"begin\": \"(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>)\",\n            \"end\": \"(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.js\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.js\"\n                },\n                \"3\": {\n                    \"name\": \"support.class.component.js\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.tag.end.js\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.js\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.js\"\n                },\n                \"3\": {\n                    \"name\": \"support.class.component.js\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.tag.end.js\"\n                }\n            },\n            \"contentName\": \"meta.jsx.children.js\",\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-children\"\n                }\n            ]\n        },\n        \"jsx-tag-in-expression\": {\n            \"begin\":\n                \"(?x)\\n  (?<=[({\\\\[,?=>:*]|&&|\\\\|\\\\||\\\\?|\\\\Wreturn|^return|\\\\Wdefault|^)\\\\s*\\n  (?!<\\\\s*[_$[:alpha:]][_$[:alnum:]]*((\\\\s+extends\\\\s+[^=>])|,)) # look ahead is not type parameter of arrow\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(/>)|(?:(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\\\s*(>))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.tag.js\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.tag.begin.js\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.js\"\n                },\n                \"4\": {\n                    \"name\": \"support.class.component.js\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.tag.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag\"\n                }\n            ]\n        },\n        \"jsx-child-tag\": {\n            \"begin\":\n                \"(?x)\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(/>)|(?:(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\\\s*(>))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.tag.js\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.js\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.tag.begin.js\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.js\"\n                },\n                \"4\": {\n                    \"name\": \"support.class.component.js\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.tag.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag\"\n                }\n            ]\n        },\n        \"jsx-tag\": {\n            \"name\": \"meta.tag.js\",\n            \"begin\":\n                \"(?x)\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(?=(/>)|(?:(</)\\\\s*([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\\\s*(>)))\",\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?x)\\n  (<)\\\\s*\\n  ((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.begin.js\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.class.component.js\"\n                        }\n                    },\n                    \"end\": \"(?=[/]?>)\",\n                    \"contentName\": \"meta.tag.attributes.js\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#jsx-tag-attributes\"\n                        },\n                        {\n                            \"include\": \"#jsx-tag-attributes-illegal\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.js\"\n                        }\n                    },\n                    \"end\": \"(?=</)\",\n                    \"contentName\": \"meta.jsx.children.js\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsx-children\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsx-children\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes\"\n                },\n                {\n                    \"include\": \"#jsx-child-tag\"\n                },\n                {\n                    \"include\": \"#jsx-evaluated-code\"\n                },\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-evaluated-code\": {\n            \"name\": \"meta.embedded.expression.js\",\n            \"begin\": \"\\\\{\",\n            \"end\": \"\\\\}\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.begin.js\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"jsx-entities\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.entity.js\",\n                    \"match\": \"(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.js\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.entity.js\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"invalid.illegal.bad-ampersand.js\",\n                    \"match\": \"&\"\n                }\n            ]\n        },\n        \"jsx-tag-attributes\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-attribute-name\"\n                },\n                {\n                    \"include\": \"#jsx-tag-attribute-assignment\"\n                },\n                {\n                    \"include\": \"#jsx-string-double-quoted\"\n                },\n                {\n                    \"include\": \"#jsx-string-single-quoted\"\n                },\n                {\n                    \"include\": \"#jsx-evaluated-code\"\n                }\n            ]\n        },\n        \"jsx-tag-attribute-name\": {\n            \"match\": \"(?x)\\n  \\\\s*\\n  ([_$a-zA-Z][-$\\\\w]*)\\n  (?=\\\\s|=|/?>|/\\\\*|//)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.js\"\n                }\n            }\n        },\n        \"jsx-tag-attribute-assignment\": {\n            \"name\": \"keyword.operator.assignment.js\",\n            \"match\": \"=(?=\\\\s*(?:'|\\\"|{|/\\\\*|//|\\\\n))\"\n        },\n        \"jsx-string-double-quoted\": {\n            \"name\": \"string.quoted.double.js\",\n            \"begin\": \"\\\"\",\n            \"end\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-string-single-quoted\": {\n            \"name\": \"string.quoted.single.js\",\n            \"begin\": \"'\",\n            \"end\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.js\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-tag-attributes-illegal\": {\n            \"name\": \"invalid.illegal.attribute.js\",\n            \"match\": \"\\\\S+\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/Microsoft/TypeScript-TmLanguage/commit/8361b1a232501c67911c81a4664a9460d7922c6b\",\n    \"name\": \"JavaScript (with React support)\",\n    \"scopeName\": \"source.js.jsx\",\n    \"fileTypes\": [\".js\", \".jsx\", \".es6\", \".mjs\"],\n    \"uuid\": \"805375ec-d614-41f5-8993-5843fe63ea82\",\n    \"patterns\": [\n        {\n            \"include\": \"#directives\"\n        },\n        {\n            \"include\": \"#statements\"\n        },\n        {\n            \"name\": \"comment.line.shebang.ts\",\n            \"match\": \"\\\\A(#!).*(?=$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.ts\"\n                }\n            }\n        }\n    ],\n    \"repository\": {\n        \"statements\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#declaration\"\n                },\n                {\n                    \"include\": \"#control-statement\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#function-declaration\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#interface-declaration\"\n                },\n                {\n                    \"include\": \"#enum-declaration\"\n                },\n                {\n                    \"include\": \"#namespace-declaration\"\n                },\n                {\n                    \"include\": \"#type-alias-declaration\"\n                },\n                {\n                    \"include\": \"#import-equals-declaration\"\n                },\n                {\n                    \"include\": \"#import-declaration\"\n                },\n                {\n                    \"include\": \"#export-declaration\"\n                }\n            ]\n        },\n        \"control-statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#switch-statement\"\n                },\n                {\n                    \"include\": \"#for-loop\"\n                },\n                {\n                    \"name\": \"keyword.control.trycatch.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(catch|finally|throw|try)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.loop.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(break|continue|do|goto|while)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.flow.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(return)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.switch.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(case|default|switch)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.conditional.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(else|if)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.with.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(with)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.other.debugger.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(debugger)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"storage.modifier.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(declare)\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#regex\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#function-expression\"\n                },\n                {\n                    \"include\": \"#class-expression\"\n                },\n                {\n                    \"include\": \"#arrow-function\"\n                },\n                {\n                    \"include\": \"#cast\"\n                },\n                {\n                    \"include\": \"#ternary-expression\"\n                },\n                {\n                    \"include\": \"#new-expr\"\n                },\n                {\n                    \"include\": \"#object-literal\"\n                },\n                {\n                    \"include\": \"#expression-operators\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#literal\"\n                },\n                {\n                    \"include\": \"#support-objects\"\n                },\n                {\n                    \"include\": \"#identifiers\"\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                }\n            ]\n        },\n        \"decorator\": {\n            \"name\": \"meta.decorator.js.jsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\@\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.decorator.js.jsx\"\n                }\n            },\n            \"end\": \"(?=\\\\s)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"var-expr\": {\n            \"name\": \"meta.var.expr.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(var|let|const(?!\\\\s+enum\\\\b))\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.js.jsx\"\n                }\n            },\n            \"end\": \"(?=$|^|;|}|(\\\\s+(of|in)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#destructuring-variable\"\n                },\n                {\n                    \"include\": \"#var-single-variable\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(,)\\\\s*(?!\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.comma.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<!,)((?==|;|}|(\\\\s+(of|in)\\\\s+)|^\\\\s*$))|((?<=\\\\S)(?=\\\\s*$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#destructuring-variable\"\n                        },\n                        {\n                            \"include\": \"#var-single-variable\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"var-single-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.var-single-variable.expr.js.jsx\",\n                    \"begin\":\n                        \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.js.jsx entity.name.function.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.js.jsx\",\n                    \"begin\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.js.jsx variable.other.constant.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.js.jsx\",\n                    \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"meta.definition.variable.js.jsx variable.other.readwrite.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"var-single-variable-type-annotation\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"destructuring-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.object-binding-pattern-variable.js.jsx\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\{)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.array-binding-pattern-variable.js.jsx\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\[)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"object-binding-element-propertyName\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.destructuring.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"variable.object.property.js.jsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-variable-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"meta.definition.variable.js.jsx variable.other.readwrite.js.jsx\"\n                }\n            }\n        },\n        \"object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-binding-element\"\n                }\n            ]\n        },\n        \"array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-name\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"\\\\s*\\\\b(public|protected|private|readonly)(?=\\\\s+(public|protected|private|readonly)\\\\s+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:(this)|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.js.jsx variable.language.this.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.function.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:((?<!\\\\.|\\\\$)\\\\bthis\\\\b(?!\\\\.|\\\\$))|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.parameter.js.jsx variable.language.this.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"variable.parameter.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.js.jsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"destructuring-parameter\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.parameter.object-binding-pattern.js.jsx\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\{)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-object-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.paramter.array-binding-pattern.js.jsx\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\[)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"parameter-object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#parameter-array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-parameter-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"variable.parameter.js.jsx\"\n                }\n            }\n        },\n        \"parameter-object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-object-binding-element\"\n                }\n            ]\n        },\n        \"parameter-array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"field-declaration\": {\n            \"name\": \"meta.field.declaration.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\()(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s+)?(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                }\n            },\n            \"end\":\n                \"(?=\\\\}|;|,|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n                    \"end\":\n                        \"(?=[};,=]|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        },\n                        {\n                            \"include\": \"#array-literal\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.js.jsx entity.name.function.js.jsx\",\n                            \"match\":\n                                \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\\\?\\\\s*)?\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\"\n                        },\n                        {\n                            \"name\":\n                                \"meta.definition.property.js.jsx variable.object.property.js.jsx\",\n                            \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.optional.js.jsx\",\n                            \"match\": \"\\\\?\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"variable-initializer\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[,);}\\\\]])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=[,);}\\\\]])|(?=^\\\\s*$)|(?<=\\\\S)(?<!=)(?=\\\\s*$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"function-declaration\": {\n            \"name\": \"meta.function.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.async.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.function.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.generator.asterisk.js.jsx\"\n                },\n                \"5\": {\n                    \"name\": \"meta.definition.function.js.jsx entity.name.function.js.jsx\"\n                }\n            },\n            \"end\": \"(?=$|^|;)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-expression\": {\n            \"name\": \"meta.function.expression.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.function.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"meta.definition.function.js.jsx entity.name.function.js.jsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-body\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                },\n                {\n                    \"include\": \"#return-type\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"method-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.method.declaration.js.jsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.property.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.generator.asterisk.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.method.declaration.js.jsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:(?:\\\\b(?:(new)|(constructor))\\\\b(?!\\\\$|\\\\.|:))|(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))?\\\\s*[\\\\(\\\\<]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.new.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"storage.type.js.jsx\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.generator.asterisk.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-literal-method-declaration\": {\n            \"name\": \"meta.method.declaration.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.property.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.js.jsx\"\n                }\n            },\n            \"end\": \"(?=\\\\}|;|,)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#method-declaration-name\"\n                },\n                {\n                    \"include\": \"#function-body\"\n                },\n                {\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.property.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.generator.asterisk.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\(|\\\\<)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"method-declaration-name\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??)\\\\s*[\\\\(\\\\<])\",\n            \"end\": \"(?=\\\\(|\\\\<)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"meta.definition.method.js.jsx entity.name.function.js.jsx\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                },\n                {\n                    \"name\": \"keyword.operator.optional.js.jsx\",\n                    \"match\": \"\\\\?\"\n                }\n            ]\n        },\n        \"arrow-function\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.arrow.js.jsx\",\n                    \"match\":\n                        \"(?:(?<!\\\\.|\\\\$)(\\\\basync)\\\\s+)?([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?==>)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.parameter.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.arrow.js.jsx\",\n                    \"begin\":\n                        \"(?x) (?:\\n  (?<!\\\\.|\\\\$)(\\\\basync)\\n)? ((?<![})!\\\\]])\\\\s*\\n  (?=\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  )\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.js.jsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameters\"\n                        },\n                        {\n                            \"include\": \"#function-parameters\"\n                        },\n                        {\n                            \"include\": \"#arrow-return-type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.arrow.js.jsx\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\}|\\\\S)(?<!=>)|((?!\\\\{)(?=\\\\S))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#decl-block\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"indexer-declaration\": {\n            \"name\": \"meta.indexer.declaration.js.jsx\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"variable.parameter.js.jsx\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                }\n            ]\n        },\n        \"indexer-mapped-type-declaration\": {\n            \"name\": \"meta.indexer.mappedtype.declaration.js.jsx\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s+(in)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.operator.expression.in.js.jsx\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"function-parameters\": {\n            \"name\": \"meta.parameters.js.jsx\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.begin.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter\"\n                },\n                {\n                    \"include\": \"#parameter-name\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"name\": \"punctuation.separator.parameter.js.jsx\",\n                    \"match\": \",\"\n                }\n            ]\n        },\n        \"class-declaration\": {\n            \"name\": \"meta.class.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(class)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.class.js.jsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-expression\": {\n            \"name\": \"meta.class.js.jsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(class)\\\\b(?=\\\\s+|[<{]|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.class.js.jsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-declaration-or-expression-patterns\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.class.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"interface-declaration\": {\n            \"name\": \"meta.interface.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(interface)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.interface.js.jsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.interface.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"class-or-interface-heritage\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:\\\\b(extends|implements)\\\\b)(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                }\n            },\n            \"end\": \"(?=\\\\{)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)(?=\\\\s*[_$[:alpha:]][_$[:alnum:]]*(\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)*\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.inherited-class.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"class-or-interface-body\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#access-modifier\"\n                },\n                {\n                    \"include\": \"#property-accessor\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"access-modifier\": {\n            \"name\": \"storage.modifier.js.jsx\",\n            \"match\":\n                \"(?<!\\\\.|\\\\$)\\\\b(abstract|public|protected|private|readonly|static)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"property-accessor\": {\n            \"name\": \"storage.type.property.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(get|set)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"enum-declaration\": {\n            \"name\": \"meta.enum.declaration.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?(?:\\\\b(const)\\\\s+)?\\\\b(enum)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.enum.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.type.enum.js.jsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"variable.other.enummember.js.jsx\"\n                                }\n                            },\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\":\n                                \"(?=((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\])))\",\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#string\"\n                                },\n                                {\n                                    \"include\": \"#array-literal\"\n                                },\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"namespace-declaration\": {\n            \"name\": \"meta.namespace.declaration.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(namespace|module)\\\\s+(?=[_$[:alpha:]\\\"'`])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.namespace.js.jsx\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\})|(?=;|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"name\": \"entity.name.type.module.js.jsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"type-alias-declaration\": {\n            \"name\": \"meta.type.declaration.js.jsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(type)\\\\b\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.type.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.alias.js.jsx\"\n                }\n            },\n            \"end\":\n                \"(?=[};]|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"match\": \"(=)\\\\s*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.js.jsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"import-equals-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.import-equals.external.js.jsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(require)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.control.require.js.jsx\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.brace.round.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.import-equals.internal.js.jsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(?!require\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=;|$|^)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"entity.name.type.module.js.jsx\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.accessor.js.jsx\"\n                                }\n                            }\n                        },\n                        {\n                            \"name\": \"variable.other.readwrite.js.jsx\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-declaration\": {\n            \"name\": \"meta.import.js.jsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)(?!(\\\\s*[:\\\\(])|(\\\\$|\\\\.))\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.js.jsx\"\n                }\n            },\n            \"end\": \"(?=;|$|^)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-declaration\"\n                }\n            ]\n        },\n        \"export-declaration\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(export)\\\\s+(as)\\\\s+(namespace)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.as.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.namespace.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.module.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.export.default.js.jsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?:(?:\\\\s*(=))|(?:\\\\s+(default)(?=\\\\s+)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.assignment.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.default.js.jsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.export.js.jsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?!(\\\\s*:)|(\\\\$))\\\\b\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.export.js.jsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#import-export-declaration\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-export-declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#import-export-block\"\n                },\n                {\n                    \"name\": \"keyword.control.from.js.jsx\",\n                    \"match\": \"\\\\bfrom\\\\b\"\n                },\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-block\": {\n            \"name\": \"meta.block.js.jsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-clause\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bdefault)|(\\\\*)|(\\\\b[_$[:alpha:]][_$[:alnum:]]*))\\\\s+(as)\\\\s+(\\\\b[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.default.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.language.import-export-all.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.control.as.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"variable.other.readwrite.alias.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"name\": \"constant.language.import-export-all.js.jsx\",\n                    \"match\": \"\\\\*\"\n                },\n                {\n                    \"name\": \"keyword.control.default.js.jsx\",\n                    \"match\": \"\\\\b(default)\\\\b\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.alias.js.jsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"switch-statement\": {\n            \"name\": \"switch-statement.expr.js.jsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?=\\\\bswitch\\\\s*\\\\()\",\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"switch-expression.expr.js.jsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(switch)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.switch.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.brace.round.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"switch-block.expr.js.jsx\",\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"case-clause.expr.js.jsx\",\n                            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(case|default(?=:))\\\\b(?!\\\\$|\\\\.)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.control.switch.js.jsx\"\n                                }\n                            },\n                            \"end\": \":\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.section.case-statement.js.jsx\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#expression\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#statements\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"for-loop\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(for)(?:\\\\s+(await))?\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.loop.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"meta.brace.round.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"decl-block\": {\n            \"name\": \"meta.block.js.jsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#statements\"\n                }\n            ]\n        },\n        \"after-operator-block-as-object-literal\": {\n            \"name\": \"meta.objectliteral.js.jsx\",\n            \"begin\":\n                \"(?<=[=(,\\\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\\\|\\\\||\\\\*)\\\\s*(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-literal\": {\n            \"name\": \"meta.objectliteral.js.jsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-member\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-literal-method-declaration\"\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx meta.object-literal.key.js.jsx\",\n                    \"begin\": \"(?=\\\\[)\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-literal\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx meta.object-literal.key.js.jsx\",\n                    \"begin\": \"(?=[\\\\'\\\\\\\"])\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"match\": \"(?![_$[:alpha:]])([[:digit:]]+)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js.jsx\"\n                        },\n                        \"1\": {\n                            \"name\": \"constant.numeric.decimal.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"match\":\n                        \"(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js.jsx\"\n                        },\n                        \"1\": {\n                            \"name\": \"entity.name.function.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"match\": \"(?:[_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=,|\\\\}|$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.readwrite.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"begin\": \"(?=[_$[:alpha:]][_$[:alnum:]]*\\\\s*=)\",\n                    \"end\": \"(?=,|\\\\}|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.js.jsx\",\n                    \"begin\": \":\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\":\n                                \"meta.object-literal.key.js.jsx punctuation.separator.key-value.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"ternary-expression\": {\n            \"begin\": \"(\\\\?)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.js.jsx\"\n                }\n            },\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"function-call\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"end\":\n                \"(?<=\\\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.function-call.js.jsx\",\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))\",\n                    \"end\":\n                        \"(?=\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#literal\"\n                        },\n                        {\n                            \"include\": \"#support-objects\"\n                        },\n                        {\n                            \"include\": \"#object-identifiers\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.expression.import.js.jsx\",\n                            \"match\": \"(?![\\\\.\\\\$])\\\\bimport(?=\\\\s*[\\\\(]\\\\s*[\\\\\\\"\\\\'\\\\`])\"\n                        },\n                        {\n                            \"name\": \"entity.name.function.js.jsx\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"meta.type.parameters.js.jsx\",\n                    \"begin\": \"\\\\<\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.begin.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.end.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                }\n            ]\n        },\n        \"new-expr\": {\n            \"name\": \"new.expr.js.jsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.new.js.jsx\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\))|(?=[;),}\\\\]]|$|((?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.))|((?<!\\\\.|\\\\$)\\\\bfunction((\\\\s+[_$[:alpha:]][_$[:alnum:]]*)|(\\\\s*[\\\\(]))))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"paren-expression\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"cast\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx\"\n                }\n            ]\n        },\n        \"expression-operators\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.flow.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(await)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(yield)\\\\b(?!\\\\$|\\\\.)(?:\\\\s*(\\\\*))?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.flow.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.generator.asterisk.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"keyword.operator.expression.delete.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bdelete\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.in.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bin\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.of.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.instanceof.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\binstanceof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.new.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.void.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bvoid\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(as)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.as.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,:})\\\\]]|((?<!\\\\.|\\\\$)\\\\b(as)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"keyword.operator.spread.js.jsx\",\n                    \"match\": \"\\\\.\\\\.\\\\.\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.js.jsx\",\n                    \"match\": \"\\\\*=|(?<!\\\\()/=|%=|\\\\+=|\\\\-=\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.bitwise.js.jsx\",\n                    \"match\": \"\\\\&=|\\\\^=|<<=|>>=|>>>=|\\\\|=\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.shift.js.jsx\",\n                    \"match\": \"<<|>>>|>>\"\n                },\n                {\n                    \"name\": \"keyword.operator.comparison.js.jsx\",\n                    \"match\": \"===|!==|==|!=\"\n                },\n                {\n                    \"name\": \"keyword.operator.relational.js.jsx\",\n                    \"match\": \"<=|>=|<>|<|>\"\n                },\n                {\n                    \"name\": \"keyword.operator.logical.js.jsx\",\n                    \"match\": \"\\\\!|&&|\\\\|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.js.jsx\",\n                    \"match\": \"\\\\&|~|\\\\^|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.js.jsx\",\n                    \"match\": \"\\\\=\"\n                },\n                {\n                    \"name\": \"keyword.operator.decrement.js.jsx\",\n                    \"match\": \"--\"\n                },\n                {\n                    \"name\": \"keyword.operator.increment.js.jsx\",\n                    \"match\": \"\\\\+\\\\+\"\n                },\n                {\n                    \"name\": \"keyword.operator.arithmetic.js.jsx\",\n                    \"match\": \"%|\\\\*|/|-|\\\\+\"\n                },\n                {\n                    \"match\": \"(?<=[_$[:alnum:])])\\\\s*(/)(?![/*])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.arithmetic.js.jsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"typeof-operator\": {\n            \"name\": \"keyword.operator.expression.typeof.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\btypeof\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#boolean-literal\"\n                },\n                {\n                    \"include\": \"#null-literal\"\n                },\n                {\n                    \"include\": \"#undefined-literal\"\n                },\n                {\n                    \"include\": \"#numericConstant-literal\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"include\": \"#this-literal\"\n                },\n                {\n                    \"include\": \"#super-literal\"\n                }\n            ]\n        },\n        \"array-literal\": {\n            \"name\": \"meta.array.literal.js.jsx\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"numeric-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.numeric.hex.js.jsx\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(x|X)[0-9a-fA-F]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.binary.js.jsx\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(b|B)[01]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.octal.js.jsx\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(o|O)?[0-7]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(?<!\\\\$)(?:\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)| # 1.1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[eE][+-]?[0-9]+\\\\b)|       # 1.E+3\\n  (?:\\\\B(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)|       # .1E+3\\n  (?:\\\\b[0-9]+[eE][+-]?[0-9]+\\\\b)|           # 1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+\\\\b)|                # 1.1\\n  (?:\\\\b[0-9]+(\\\\.)\\\\B)|                      # 1.\\n  (?:\\\\B(\\\\.)[0-9]+\\\\b)|                      # .1\\n  (?:\\\\b[0-9]+\\\\b(?!\\\\.))                     # 1\\n)(?!\\\\$)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"constant.numeric.decimal.js.jsx\"\n                        },\n                        \"1\": {\n                            \"name\": \"meta.delimiter.decimal.period.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.delimiter.decimal.period.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.delimiter.decimal.period.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.delimiter.decimal.period.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"meta.delimiter.decimal.period.js.jsx\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.delimiter.decimal.period.js.jsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"boolean-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.boolean.true.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\btrue\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.boolean.false.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bfalse\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"null-literal\": {\n            \"name\": \"constant.language.null.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bnull\\\\b(?!\\\\$)\"\n        },\n        \"this-literal\": {\n            \"name\": \"variable.language.this.js.jsx\",\n            \"match\": \"(?<!\\\\$)((?<=\\\\.\\\\.\\\\.)|(?<!\\\\.))\\\\bthis\\\\b(?!\\\\$)\"\n        },\n        \"super-literal\": {\n            \"name\": \"variable.language.super.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bsuper\\\\b(?!\\\\$)\"\n        },\n        \"undefined-literal\": {\n            \"name\": \"constant.language.undefined.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bundefined\\\\b(?!\\\\$)\"\n        },\n        \"numericConstant-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.nan.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bNaN\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.infinity.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bInfinity\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"support-objects\": {\n            \"patterns\": [\n                {\n                    \"name\": \"variable.language.arguments.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(arguments)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.builtin.js.jsx\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Array|ArrayBuffer|Atomics|Boolean|DataView|Date|Float32Array|Float64Array|Function|Generator\\n  |GeneratorFunction|Int8Array|Int16Array|Int32Array|Intl|Map|Number|Object|Promise|Proxy\\n  |Reflect|RegExp|Set|SharedArrayBuffer|SIMD|String|Symbol|TypedArray\\n  |Uint8Array|Uint16Array|Uint32Array|Uint8ClampedArray|WeakMap|WeakSet)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.error.js.jsx\",\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b((Eval|Internal|Range|Reference|Syntax|Type|URI)?Error)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.function.js.jsx\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(clear(Interval|Timeout)|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|\\n  isFinite|isNaN|parseFloat|parseInt|require|set(Interval|Timeout)|super|unescape|uneval)(?=\\\\s*\\\\()\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Math)(?:\\\\s*(\\\\.)\\\\s*(?:\\n  (abs|acos|acosh|asin|asinh|atan|atan2|atanh|cbrt|ceil|clz32|cos|cosh|exp|\\n  expm1|floor|fround|hypot|imul|log|log10|log1p|log2|max|min|pow|random|\\n  round|sign|sin|sinh|sqrt|tan|tanh|trunc)\\n  |\\n  (E|LN10|LN2|LOG10E|LOG2E|PI|SQRT1_2|SQRT2)))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.math.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.math.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.constant.property.math.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(console)(?:\\\\s*(\\\\.)\\\\s*(\\n  assert|clear|count|debug|dir|error|group|groupCollapsed|groupEnd|info|log\\n  |profile|profileEnd|table|time|timeEnd|timeStamp|trace|warn))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.class.console.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.console.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(JSON)(?:\\\\s*(\\\\.)\\\\s*(parse|stringify))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.json.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.json.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (constructor|length|prototype|__proto__)\\n  |\\n  (EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.variable.property.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.constant.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (?<!\\\\.|\\\\$) \\\\b (?:\\n  (document|event|navigator|performance|screen|window)\\n  |\\n  (AnalyserNode|ArrayBufferView|Attr|AudioBuffer|AudioBufferSourceNode|AudioContext|AudioDestinationNode|AudioListener\\n  |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule\\n  |CSSCounterStyleRule|CSSGroupingRule|CSSMatrix|CSSMediaRule|CSSPageRule|CSSPrimitiveValue|CSSRule|CSSRuleList|CSSStyleDeclaration\\n  |CSSStyleRule|CSSStyleSheet|CSSSupportsRule|CSSValue|CSSValueList|CanvasGradient|CanvasImageSource|CanvasPattern\\n  |CanvasRenderingContext2D|ChannelMergerNode|ChannelSplitterNode|CharacterData|ChromeWorker|CloseEvent|Comment|CompositionEvent\\n  |Console|ConvolverNode|Coordinates|Credential|CredentialsContainer|Crypto|CryptoKey|CustomEvent|DOMError|DOMException\\n  |DOMHighResTimeStamp|DOMImplementation|DOMString|DOMStringList|DOMStringMap|DOMTimeStamp|DOMTokenList|DataTransfer\\n  |DataTransferItem|DataTransferItemList|DedicatedWorkerGlobalScope|DelayNode|DeviceProximityEvent|DirectoryEntry\\n  |DirectoryEntrySync|DirectoryReader|DirectoryReaderSync|Document|DocumentFragment|DocumentTouch|DocumentType|DragEvent\\n  |DynamicsCompressorNode|Element|Entry|EntrySync|ErrorEvent|Event|EventListener|EventSource|EventTarget|FederatedCredential\\n  |FetchEvent|File|FileEntry|FileEntrySync|FileException|FileList|FileReader|FileReaderSync|FileSystem|FileSystemSync\\n  |FontFace|FormData|GainNode|Gamepad|GamepadButton|GamepadEvent|Geolocation|GlobalEventHandlers|HTMLAnchorElement\\n  |HTMLAreaElement|HTMLAudioElement|HTMLBRElement|HTMLBaseElement|HTMLBodyElement|HTMLButtonElement|HTMLCanvasElement\\n  |HTMLCollection|HTMLContentElement|HTMLDListElement|HTMLDataElement|HTMLDataListElement|HTMLDialogElement|HTMLDivElement\\n  |HTMLDocument|HTMLElement|HTMLEmbedElement|HTMLFieldSetElement|HTMLFontElement|HTMLFormControlsCollection|HTMLFormElement\\n  |HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLIFrameElement|HTMLImageElement|HTMLInputElement\\n  |HTMLKeygenElement|HTMLLIElement|HTMLLabelElement|HTMLLegendElement|HTMLLinkElement|HTMLMapElement|HTMLMediaElement\\n  |HTMLMetaElement|HTMLMeterElement|HTMLModElement|HTMLOListElement|HTMLObjectElement|HTMLOptGroupElement|HTMLOptionElement\\n  |HTMLOptionsCollection|HTMLOutputElement|HTMLParagraphElement|HTMLParamElement|HTMLPreElement|HTMLProgressElement\\n  |HTMLQuoteElement|HTMLScriptElement|HTMLSelectElement|HTMLShadowElement|HTMLSourceElement|HTMLSpanElement|HTMLStyleElement\\n  |HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement\\n  |HTMLTableRowElement|HTMLTableSectionElement|HTMLTextAreaElement|HTMLTimeElement|HTMLTitleElement|HTMLTrackElement\\n  |HTMLUListElement|HTMLUnknownElement|HTMLVideoElement|HashChangeEvent|History|IDBCursor|IDBCursorWithValue|IDBDatabase\\n  |IDBEnvironment|IDBFactory|IDBIndex|IDBKeyRange|IDBMutableFile|IDBObjectStore|IDBOpenDBRequest|IDBRequest|IDBTransaction\\n  |IDBVersionChangeEvent|IIRFilterNode|IdentityManager|ImageBitmap|ImageBitmapFactories|ImageData|Index|InputDeviceCapabilities\\n  |InputEvent|InstallEvent|InstallTrigger|KeyboardEvent|LinkStyle|LocalFileSystem|LocalFileSystemSync|Location|MIDIAccess\\n  |MIDIConnectionEvent|MIDIInput|MIDIInputMap|MIDIOutputMap|MediaElementAudioSourceNode|MediaError|MediaKeyMessageEvent\\n  |MediaKeySession|MediaKeyStatusMap|MediaKeySystemAccess|MediaKeySystemConfiguration|MediaKeys|MediaRecorder|MediaStream\\n  |MediaStreamAudioDestinationNode|MediaStreamAudioSourceNode|MessageChannel|MessageEvent|MessagePort|MouseEvent\\n  |MutationObserver|MutationRecord|NamedNodeMap|Navigator|NavigatorConcurrentHardware|NavigatorGeolocation|NavigatorID\\n  |NavigatorLanguage|NavigatorOnLine|Node|NodeFilter|NodeIterator|NodeList|NonDocumentTypeChildNode|Notification\\n  |OfflineAudioCompletionEvent|OfflineAudioContext|OscillatorNode|PageTransitionEvent|PannerNode|ParentNode|PasswordCredential\\n  |Path2D|PaymentAddress|PaymentRequest|PaymentResponse|Performance|PerformanceEntry|PerformanceFrameTiming|PerformanceMark\\n  |PerformanceMeasure|PerformanceNavigation|PerformanceNavigationTiming|PerformanceObserver|PerformanceObserverEntryList\\n  |PerformanceResourceTiming|PerformanceTiming|PeriodicSyncEvent|PeriodicWave|Plugin|Point|PointerEvent|PopStateEvent\\n  |PortCollection|Position|PositionError|PositionOptions|PresentationConnectionClosedEvent|PresentationConnectionList\\n  |PresentationReceiver|ProcessingInstruction|ProgressEvent|PromiseRejectionEvent|PushEvent|PushRegistrationManager\\n  |RTCCertificate|RTCConfiguration|RTCPeerConnection|RTCSessionDescriptionCallback|RTCStatsReport|RadioNodeList|RandomSource\\n  |Range|ReadableByteStream|RenderingContext|SVGAElement|SVGAngle|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement\\n  |SVGAnimateTransformElement|SVGAnimatedAngle|SVGAnimatedBoolean|SVGAnimatedEnumeration|SVGAnimatedInteger|SVGAnimatedLength\\n  |SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedPoints|SVGAnimatedPreserveAspectRatio\\n  |SVGAnimatedRect|SVGAnimatedString|SVGAnimatedTransformList|SVGAnimationElement|SVGCircleElement|SVGClipPathElement\\n  |SVGCursorElement|SVGDefsElement|SVGDescElement|SVGElement|SVGEllipseElement|SVGEvent|SVGFilterElement|SVGFontElement\\n  |SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement\\n  |SVGForeignObjectElement|SVGGElement|SVGGlyphElement|SVGGradientElement|SVGHKernElement|SVGImageElement|SVGLength\\n  |SVGLengthList|SVGLineElement|SVGLinearGradientElement|SVGMPathElement|SVGMaskElement|SVGMatrix|SVGMissingGlyphElement\\n  |SVGNumber|SVGNumberList|SVGPathElement|SVGPatternElement|SVGPoint|SVGPolygonElement|SVGPolylineElement|SVGPreserveAspectRatio\\n  |SVGRadialGradientElement|SVGRect|SVGRectElement|SVGSVGElement|SVGScriptElement|SVGSetElement|SVGStopElement|SVGStringList\\n  |SVGStylable|SVGStyleElement|SVGSwitchElement|SVGSymbolElement|SVGTRefElement|SVGTSpanElement|SVGTests|SVGTextElement\\n  |SVGTextPositioningElement|SVGTitleElement|SVGTransform|SVGTransformList|SVGTransformable|SVGUseElement|SVGVKernElement\\n  |SVGViewElement|ServiceWorker|ServiceWorkerContainer|ServiceWorkerGlobalScope|ServiceWorkerRegistration|ServiceWorkerState\\n  |ShadowRoot|SharedWorker|SharedWorkerGlobalScope|SourceBufferList|StereoPannerNode|Storage|StorageEvent|StyleSheet\\n  |StyleSheetList|SubtleCrypto|SyncEvent|Text|TextMetrics|TimeEvent|TimeRanges|Touch|TouchEvent|TouchList|Transferable\\n  |TreeWalker|UIEvent|USVString|VRDisplayCapabilities|ValidityState|WaveShaperNode|WebGL|WebGLActiveInfo|WebGLBuffer\\n  |WebGLContextEvent|WebGLFramebuffer|WebGLProgram|WebGLRenderbuffer|WebGLRenderingContext|WebGLShader|WebGLShaderPrecisionFormat\\n  |WebGLTexture|WebGLTimerQueryEXT|WebGLTransformFeedback|WebGLUniformLocation|WebGLVertexArrayObject|WebGLVertexArrayObjectOES\\n  |WebSocket|WebSockets|WebVTT|WheelEvent|Window|WindowBase64|WindowEventHandlers|WindowTimers|Worker|WorkerGlobalScope\\n  |WorkerLocation|WorkerNavigator|XMLHttpRequest|XMLHttpRequestEventTarget|XMLSerializer|XPathExpression|XPathResult\\n  |XSLTProcessor))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.dom.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.class.dom.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\\n  |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\\n  |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\\n  |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\\n  |\\n  (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\\n  |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\\n  |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\\n  |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\\n  |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\\n  |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\\n  |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\\n  |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\\n  |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\\n  |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\\n  |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\\n  |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\\n  |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\\n  |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\\n  |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\\n  |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\\n  |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\\n  |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\\n  |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\\n  |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\\n  |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\\n  |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\\n  |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\\n  |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\\n  |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\\n  |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\\\b(?!\\\\$|\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.constant.dom.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.dom.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.class.node.js.jsx\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Buffer|EventEmitter|Server|Pipe|Socket|REPLServer|ReadStream|WriteStream|Stream\\n  |Inflate|Deflate|InflateRaw|DeflateRaw|GZip|GUnzip|Unzip|Zip)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(process)(?:(\\\\.)(?:\\n  (arch|argv|config|connected|env|execArgv|execPath|exitCode|mainModule|pid|platform|release|stderr|stdin|stdout|title|version|versions)\\n  |\\n  (abort|chdir|cwd|disconnect|exit|[sg]ete?[gu]id|send|[sg]etgroups|initgroups|kill|memoryUsage|nextTick|umask|uptime|hrtime)\\n))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.object.process.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.process.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.process.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(?:(exports)|(module)(?:(\\\\.)(exports|id|filename|loaded|parent|children))?)\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.type.object.module.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.type.object.module.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.type.object.module.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.variable.object.node.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(global|GLOBAL|root|__dirname|__filename)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s*\\n(?:\\n (on(?:Rowsinserted|Rowsdelete|Rowenter|Rowexit|Resize|Resizestart|Resizeend|Reset|\\n   Readystatechange|Mouseout|Mouseover|Mousedown|Mouseup|Mousemove|\\n   Before(?:cut|deactivate|unload|update|paste|print|editfocus|activate)|\\n   Blur|Scrolltop|Submit|Select|Selectstart|Selectionchange|Hover|Help|\\n   Change|Contextmenu|Controlselect|Cut|Cellchange|Clock|Close|Deactivate|\\n   Datasetchanged|Datasetcomplete|Dataavailable|Drop|Drag|Dragstart|Dragover|\\n   Dragdrop|Dragenter|Dragend|Dragleave|Dblclick|Unload|Paste|Propertychange|Error|\\n   Errorupdate|Keydown|Keyup|Keypress|Focus|Load|Activate|Afterupdate|Afterprint|Abort)\\n ) |\\n (shift|showModelessDialog|showModalDialog|showHelp|scroll|scrollX|scrollByPages|\\n   scrollByLines|scrollY|scrollTo|stop|strike|sizeToContent|sidebar|signText|sort|\\n   sup|sub|substr|substring|splice|split|send|set(?:Milliseconds|Seconds|Minutes|Hours|\\n   Month|Year|FullYear|Date|UTC(?:Milliseconds|Seconds|Minutes|Hours|Month|FullYear|Date)|\\n   Time|Hotkeys|Cursor|ZOptions|Active|Resizable|RequestHeader)|search|slice|\\n   savePreferences|small|home|handleEvent|navigate|char|charCodeAt|charAt|concat|\\n   contextual|confirm|compile|clear|captureEvents|call|createStyleSheet|createPopup|\\n   createEventObject|to(?:GMTString|UTCString|String|Source|UpperCase|LowerCase|LocaleString)|\\n   test|taint|taintEnabled|indexOf|italics|disableExternalCapture|dump|detachEvent|unshift|\\n   untaint|unwatch|updateCommands|join|javaEnabled|pop|push|plugins.refresh|paddings|parse|\\n   print|prompt|preference|enableExternalCapture|exec|execScript|valueOf|UTC|find|file|\\n   fileModifiedDate|fileSize|fileCreatedDate|fileUpdatedDate|fixed|fontsize|fontcolor|\\n   forward|fromCharCode|watch|link|load|lastIndexOf|anchor|attachEvent|atob|apply|alert|\\n   abort|routeEvents|resize|resizeBy|resizeTo|recalc|returnValue|replace|reverse|reload|\\n   releaseCapture|releaseEvents|go|get(?:Milliseconds|Seconds|Minutes|Hours|Month|Day|Year|FullYear|\\n   Time|Date|TimezoneOffset|UTC(?:Milliseconds|Seconds|Minutes|Hours|Day|Month|FullYear|Date)|\\n   Attention|Selection|ResponseHeader|AllResponseHeaders)|moveBy|moveBelow|moveTo|\\n   moveToAbsolute|moveAbove|mergeAttributes|match|margins|btoa|big|bold|borderWidths|blink|back\\n ) |\\n (acceptNode|add|addEventListener|addTextTrack|adoptNode|after|animate|append|\\n   appendChild|appendData|before|blur|canPlayType|captureStream|\\n   caretPositionFromPoint|caretRangeFromPoint|checkValidity|clear|click|\\n   cloneContents|cloneNode|cloneRange|close|closest|collapse|\\n   compareBoundaryPoints|compareDocumentPosition|comparePoint|contains|\\n   convertPointFromNode|convertQuadFromNode|convertRectFromNode|createAttribute|\\n   createAttributeNS|createCaption|createCDATASection|createComment|\\n   createContextualFragment|createDocument|createDocumentFragment|\\n   createDocumentType|createElement|createElementNS|createEntityReference|\\n   createEvent|createExpression|createHTMLDocument|createNodeIterator|\\n   createNSResolver|createProcessingInstruction|createRange|createShadowRoot|\\n   createTBody|createTextNode|createTFoot|createTHead|createTreeWalker|delete|\\n   deleteCaption|deleteCell|deleteContents|deleteData|deleteRow|deleteTFoot|\\n   deleteTHead|detach|disconnect|dispatchEvent|elementFromPoint|elementsFromPoint|\\n   enableStyleSheetsForSet|entries|evaluate|execCommand|exitFullscreen|\\n   exitPointerLock|expand|extractContents|fastSeek|firstChild|focus|forEach|get|\\n   getAll|getAnimations|getAttribute|getAttributeNames|getAttributeNode|\\n   getAttributeNodeNS|getAttributeNS|getBoundingClientRect|getBoxQuads|\\n   getClientRects|getContext|getDestinationInsertionPoints|getElementById|\\n   getElementsByClassName|getElementsByName|getElementsByTagName|\\n   getElementsByTagNameNS|getItem|getNamedItem|getSelection|getStartDate|\\n   getVideoPlaybackQuality|has|hasAttribute|hasAttributeNS|hasAttributes|\\n   hasChildNodes|hasFeature|hasFocus|importNode|initEvent|insertAdjacentElement|\\n   insertAdjacentHTML|insertAdjacentText|insertBefore|insertCell|insertData|\\n   insertNode|insertRow|intersectsNode|isDefaultNamespace|isEqualNode|\\n   isPointInRange|isSameNode|item|key|keys|lastChild|load|lookupNamespaceURI|\\n   lookupPrefix|matches|move|moveAttribute|moveAttributeNode|moveChild|\\n   moveNamedItem|namedItem|nextNode|nextSibling|normalize|observe|open|\\n   parentNode|pause|play|postMessage|prepend|preventDefault|previousNode|\\n   previousSibling|probablySupportsContext|queryCommandEnabled|\\n   queryCommandIndeterm|queryCommandState|queryCommandSupported|queryCommandValue|\\n   querySelector|querySelectorAll|registerContentHandler|registerElement|\\n   registerProtocolHandler|releaseCapture|releaseEvents|remove|removeAttribute|\\n   removeAttributeNode|removeAttributeNS|removeChild|removeEventListener|\\n   removeItem|replace|replaceChild|replaceData|replaceWith|reportValidity|\\n   requestFullscreen|requestPointerLock|reset|scroll|scrollBy|scrollIntoView|\\n   scrollTo|seekToNextFrame|select|selectNode|selectNodeContents|set|setAttribute|\\n   setAttributeNode|setAttributeNodeNS|setAttributeNS|setCapture|\\n   setCustomValidity|setEnd|setEndAfter|setEndBefore|setItem|setNamedItem|\\n   setRangeText|setSelectionRange|setSinkId|setStart|setStartAfter|setStartBefore|\\n   slice|splitText|stepDown|stepUp|stopImmediatePropagation|stopPropagation|\\n   submit|substringData|supports|surroundContents|takeRecords|terminate|toBlob|\\n   toDataURL|toggle|toString|values|write|writeln\\n )\\n)(?=\\\\s*\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.function.event-handler.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.dom.js.jsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"identifiers\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#object-identifiers\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:(\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.property.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.property.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"variable.other.constant.js.jsx\",\n                    \"match\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.js.jsx\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"object-identifiers\": {\n            \"patterns\": [\n                {\n                    \"name\": \"support.class.js.jsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\\\.\\\\s*prototype\\\\b(?!\\\\$))\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(\\\\.)\\\\s*(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.object.property.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.object.property.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.constant.object.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.object.js.jsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"type-annotation\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.annotation.js.jsx\",\n                    \"begin\": \"(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js.jsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=$|^|[,);\\\\}\\\\]]|//)|(?==[^>])|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.annotation.js.jsx\",\n                    \"begin\": \"(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js.jsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=[,);\\\\}\\\\]]|//)|(?==[^>])|(?=^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$))|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.return.type.js.jsx\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])(?=$|^|[{};,]|//)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.return.type.js.jsx\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])((?=[{};,]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<=[:|&])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"arrow-return-type\": {\n            \"name\": \"meta.return.type.arrow.js.jsx\",\n            \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.type.annotation.js.jsx\"\n                }\n            },\n            \"end\":\n                \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=[:])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-parameters\": {\n            \"name\": \"meta.type.parameters.js.jsx\",\n            \"begin\": \"(<)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.begin.js.jsx\"\n                }\n            },\n            \"end\": \"(>)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"storage.modifier.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(extends)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.js.jsx\",\n                    \"match\": \"\\\\=(?!>)\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#type-primitive\"\n                },\n                {\n                    \"include\": \"#type-builtin-literals\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type-tuple\"\n                },\n                {\n                    \"include\": \"#type-object\"\n                },\n                {\n                    \"include\": \"#type-operators\"\n                },\n                {\n                    \"include\": \"#type-fn-type-parameters\"\n                },\n                {\n                    \"include\": \"#type-paren-or-function-parameters\"\n                },\n                {\n                    \"include\": \"#type-function-return-type\"\n                },\n                {\n                    \"include\": \"#type-name\"\n                }\n            ]\n        },\n        \"type-primitive\": {\n            \"name\": \"support.type.primitive.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(string|number|boolean|symbol|any|void|never)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-builtin-literals\": {\n            \"name\": \"support.type.builtin.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(this|true|false|undefined|null|object)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-tuple\": {\n            \"name\": \"meta.type.tuple.js.jsx\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type-object\": {\n            \"name\": \"meta.object.type.js.jsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-mapped-type-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-paren-or-function-parameters\": {\n            \"name\": \"meta.type.paren.cover.js.jsx\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                }\n            ]\n        },\n        \"type-fn-type-parameters\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.constructor.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?=\\\\s*\\\\<)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.type.constructor.js.jsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b\\\\s*(?=\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.js.jsx\",\n                    \"begin\":\n                        \"(?x)(\\n  (?=\\n    [(]\\\\s*(\\n      ([)]) |\\n      (\\\\.\\\\.\\\\.) |\\n      ([_$[:alnum:]]+\\\\s*(\\n        ([:,?=])|\\n        ([)]\\\\s*=>)\\n      ))\\n    )\\n  )\\n)\",\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.function.return.js.jsx\",\n                    \"begin\": \"(=>)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.arrow.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])(?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.return.js.jsx\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])((?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<==>)(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-operators\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"begin\": \"([&|])(?=\\\\s*\\\\{)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"[&|]\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\S)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.keyof.js.jsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bkeyof\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"type-predicate-operator\": {\n            \"name\": \"keyword.operator.expression.is.js.jsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bis\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-name\": {\n            \"patterns\": [\n                {\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.js.jsx\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"punctuation-comma\": {\n            \"name\": \"punctuation.separator.comma.js.jsx\",\n            \"match\": \",\"\n        },\n        \"punctuation-semicolon\": {\n            \"name\": \"punctuation.terminator.statement.js.jsx\",\n            \"match\": \";\"\n        },\n        \"punctuation-accessor\": {\n            \"name\": \"punctuation.accessor.js.jsx\",\n            \"match\": \"\\\\.\"\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#qstring-single\"\n                },\n                {\n                    \"include\": \"#qstring-double\"\n                }\n            ]\n        },\n        \"qstring-double\": {\n            \"name\": \"string.quoted.double.js.jsx\",\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js.jsx\"\n                }\n            },\n            \"end\": \"(\\\")|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"qstring-single\": {\n            \"name\": \"string.quoted.single.js.jsx\",\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js.jsx\"\n                }\n            },\n            \"end\": \"(\\\\')|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"string-character-escape\": {\n            \"name\": \"constant.character.escape.js.jsx\",\n            \"match\": \"\\\\\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)\"\n        },\n        \"template\": {\n            \"name\": \"string.template.js.jsx\",\n            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)?(`)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.tagged-template.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.template.begin.js.jsx\"\n                }\n            },\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.template.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#template-substitution-element\"\n                },\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"template-substitution-element\": {\n            \"name\": \"meta.template.expression.js.jsx\",\n            \"begin\": \"\\\\$\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.begin.js.jsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ],\n            \"contentName\": \"meta.embedded.line.js.jsx\"\n        },\n        \"regex\": {\n            \"patterns\": [\n                {\n                    \"name\": \"string.regexp.js.jsx\",\n                    \"begin\":\n                        \"(?<=[=(:,\\\\[?+!]|return|case|=>|&&|\\\\|\\\\||\\\\*\\\\/)\\\\s*(\\\\/)(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.regexp.js.jsx\",\n                    \"begin\":\n                        \"(?<![_$[:alnum:])])\\\\/(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"regexp\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.anchor.regexp\",\n                    \"match\": \"\\\\\\\\[bB]|\\\\^|\\\\$\"\n                },\n                {\n                    \"name\": \"keyword.other.back-reference.regexp\",\n                    \"match\": \"\\\\\\\\[1-9]\\\\d*\"\n                },\n                {\n                    \"name\": \"keyword.operator.quantifier.regexp\",\n                    \"match\": \"[?+*]|\\\\{(\\\\d+,\\\\d+|\\\\d+,|,\\\\d+|\\\\d+)\\\\}\\\\??\"\n                },\n                {\n                    \"name\": \"keyword.operator.or.regexp\",\n                    \"match\": \"\\\\|\"\n                },\n                {\n                    \"name\": \"meta.group.assertion.regexp\",\n                    \"begin\": \"(\\\\()((\\\\?=)|(\\\\?!))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.group.assertion.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.assertion.look-ahead.regexp\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.assertion.negative-look-ahead.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.group.regexp\",\n                    \"begin\": \"\\\\((\\\\?:)?\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.no-capture.regexp\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"constant.other.character-class.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"constant.other.character-class.range.regexp\",\n                            \"match\":\n                                \"(?:.|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\\\\-(?:[^\\\\]\\\\\\\\]|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"2\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"3\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                },\n                                \"4\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"5\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"6\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#regex-character-class\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#regex-character-class\"\n                }\n            ]\n        },\n        \"regex-character-class\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.character-class.regexp\",\n                    \"match\": \"\\\\\\\\[wWsSdDtrnvf]|\\\\.\"\n                },\n                {\n                    \"name\": \"constant.character.numeric.regexp\",\n                    \"match\": \"\\\\\\\\([0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})\"\n                },\n                {\n                    \"name\": \"constant.character.control.regexp\",\n                    \"match\": \"\\\\\\\\c[A-Z]\"\n                },\n                {\n                    \"name\": \"constant.character.escape.backslash.regexp\",\n                    \"match\": \"\\\\\\\\.\"\n                }\n            ]\n        },\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.block.documentation.js.jsx\",\n                    \"begin\": \"/\\\\*\\\\*(?!/)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#docblock\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"comment.block.js.jsx\",\n                    \"begin\": \"(/\\\\*)(?:\\\\s*((@)internal)(?=\\\\s|(\\\\*/)))?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.internaldeclaration.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.js.jsx\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"comment.line.double-slash.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.comment.js.jsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.internaldeclaration.js.jsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=^)\",\n                    \"contentName\": \"comment.line.double-slash.js.jsx\"\n                }\n            ]\n        },\n        \"directives\": {\n            \"name\": \"comment.line.triple-slash.directive.js.jsx\",\n            \"begin\":\n                \"^(///)\\\\s*(?=<(reference|amd-dependency|amd-module)(\\\\s+(path|types|no-default-lib|name)\\\\s*=\\\\s*((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")))+\\\\s*/>\\\\s*$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.js.jsx\"\n                }\n            },\n            \"end\": \"(?=^)\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.tag.js.jsx\",\n                    \"begin\": \"(<)(reference|amd-dependency|amd-module)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.directive.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.directive.js.jsx\"\n                        }\n                    },\n                    \"end\": \"/>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.tag.directive.js.jsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"entity.other.attribute-name.directive.js.jsx\",\n                            \"match\": \"path|types|no-default-lib|name\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.assignment.js.jsx\",\n                            \"match\": \"=\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"docblock\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n((@)(?:access|api))\\n\\\\s+\\n(private|protected|public)\\n\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.access-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)author)\\n\\\\s+\\n(\\n  [^@\\\\s<>*/]\\n  (?:[^@<>*/]|\\\\*[^/])*\\n)\\n(?:\\n  \\\\s*\\n  (<)\\n  ([^>\\\\s]+)\\n  (>)\\n)?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"constant.other.email.link.underline.jsdoc\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)borrows) \\\\s+\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <that namepath>\\n\\\\s+ (as) \\\\s+              # as\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <this namepath>\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.control.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.example.jsdoc\",\n                    \"begin\": \"((@)example)\\\\s+\",\n                    \"end\": \"(?=@|\\\\*/)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"^\\\\s\\\\*\\\\s+\"\n                        },\n                        {\n                            \"contentName\": \"constant.other.description.jsdoc\",\n                            \"begin\": \"\\\\G(<)caption(>)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            },\n                            \"end\": \"(</)caption(>)|(?=\\\\*/)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"[^\\\\s@*](?:[^*]|\\\\*[^/])*\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"source.embedded.js.jsx\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x) ((@)kind) \\\\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.symbol-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)see)\\n\\\\s+\\n(?:\\n  # URL\\n  (\\n    (?=https?://)\\n    (?:[^\\\\s*]|\\\\*[^/])+\\n  )\\n  |\\n  # JSDoc namepath\\n  (\\n    (?!\\n      # Avoid matching bare URIs (also acceptable as links)\\n      https?://\\n      |\\n      # Avoid matching {@inline tags}; we match those below\\n      (?:\\\\[[^\\\\[\\\\]]*\\\\])? # Possible description [preceding]{@tag}\\n      {@(?:link|linkcode|linkplain|tutorial)\\\\b\\n    )\\n    # Matched namepath\\n    (?:[^@\\\\s*/]|\\\\*[^/])+\\n  )\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.link.underline.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)template)\\n\\\\s+\\n# One or more valid identifiers\\n(\\n  [A-Za-z_$]         # First character: non-numeric word character\\n  [\\\\w$.\\\\[\\\\]]*        # Rest of identifier\\n  (?:                # Possible list of additional identifiers\\n    \\\\s* , \\\\s*\\n    [A-Za-z_$]\\n    [\\\\w$.\\\\[\\\\]]*\\n  )*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:arg|argument|const|constant|member|namespace|param|var)\\n)\\n\\\\s+\\n(\\n  [A-Za-z_$]\\n  [\\\\w$.\\\\[\\\\]]*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"((@)typedef)\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"entity.name.type.instance.jsdoc\",\n                            \"match\": \"(?:[^@\\\\s*/]|\\\\*[^/])+\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\": \"([A-Za-z_$][\\\\w$.\\\\[\\\\]]*)\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\":\n                                \"(?x)\\n(\\\\[)\\\\s*\\n[\\\\w$]+\\n(?:\\n  (?:\\\\[\\\\])?                                        # Foo[ ].bar properties within an array\\n  \\\\.                                                # Foo.Bar namespaced parameter\\n  [\\\\w$]+\\n)*\\n(?:\\n  \\\\s*\\n  (=)                                                # [foo=bar] Default parameter value\\n  \\\\s*\\n  (\\n    # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\\n    (?>\\n      \\\"(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!\\\"))|[^*\\\\\\\\])*?\\\" |                      # [foo=\\\"bar\\\"] Double-quoted\\n      '(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!'))|[^*\\\\\\\\])*?' |                      # [foo='bar'] Single-quoted\\n      \\\\[ (?:(?:\\\\*(?!/))|[^*])*? \\\\] |                                # [foo=[1,2]] Array literal\\n      (?:(?:\\\\*(?!/))|\\\\s(?!\\\\s*\\\\])|\\\\[.*?(?:\\\\]|(?=\\\\*/))|[^*\\\\s\\\\[\\\\]])*   # Everything else\\n    )*\\n  )\\n)?\\n\\\\s*(?:(\\\\])((?:[^*\\\\s]|\\\\*[^\\\\s/])+)?|(?=\\\\*/))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.begin.bracket.square.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"keyword.operator.assignment.jsdoc\"\n                                },\n                                \"3\": {\n                                    \"name\": \"source.embedded.js.jsx\"\n                                },\n                                \"4\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.end.bracket.square.jsdoc\"\n                                },\n                                \"5\": {\n                                    \"name\": \"invalid.illegal.syntax.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:define|enum|exception|export|extends|lends|implements|modifies\\n  |namespace|private|protected|returns?|suppress|this|throws|type\\n  |yields?)\\n)\\n\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:alias|augments|callback|constructs|emits|event|fires|exports?\\n  |extends|external|function|func|host|lends|listens|interface|memberof!?\\n  |method|module|mixes|mixin|name|requires|see|this|typedef|uses)\\n)\\n\\\\s+\\n(\\n  (?:\\n    [^{}@\\\\s*] | \\\\*[^/]\\n  )+\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"contentName\": \"variable.other.jsdoc\",\n                    \"begin\": \"((@)(?:default(?:value)?|license|version))\\\\s+(([''\\\"]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(\\\\3)|(?=$|\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"((@)(?:default(?:value)?|license|tutorial|variation|version))\\\\s+([^\\\\s*]+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"storage.type.class.jsdoc\",\n                    \"match\":\n                        \"(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#inline-tags\"\n                }\n            ]\n        },\n        \"brackets\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\[\",\n                    \"end\": \"\\\\]|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"inline-tags\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.description.jsdoc\",\n                    \"match\": \"(\\\\[)[^\\\\]]+(\\\\])(?={@(?:link|linkcode|linkplain|tutorial))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.square.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.square.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"({)((@)(?:link(?:code|plain)?|tutorial))\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.inline.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\G((?=https?://)(?:[^|}\\\\s*]|\\\\*[/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.link.underline.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"\\\\G((?:[^{}@\\\\s|*]|\\\\*[^/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.description.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsdoctype\": {\n            \"patterns\": [\n                {\n                    \"name\": \"invalid.illegal.type.jsdoc\",\n                    \"match\": \"\\\\G{(?:[^}*]|\\\\*[^/}])+$\"\n                },\n                {\n                    \"contentName\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"\\\\G({)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"((}))\\\\s*|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsx\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes-in-expression\"\n                },\n                {\n                    \"include\": \"#jsx-tag-in-expression\"\n                }\n            ]\n        },\n        \"jsx-tag-without-attributes-in-expression\": {\n            \"begin\":\n                \"(?x)\\n  (?<=[({\\\\[,?=>:*]|&&|\\\\|\\\\||\\\\?|\\\\Wreturn|^return|\\\\Wdefault|^)\\\\s*\\n  (?=(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>))\",\n            \"end\": \"(?!\\\\s*(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes\"\n                }\n            ]\n        },\n        \"jsx-tag-without-attributes\": {\n            \"name\": \"meta.tag.without-attributes.js.jsx\",\n            \"begin\": \"(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>)\",\n            \"end\": \"(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"support.class.component.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"support.class.component.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                }\n            },\n            \"contentName\": \"meta.jsx.children.js.jsx\",\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-children\"\n                }\n            ]\n        },\n        \"jsx-tag-in-expression\": {\n            \"begin\":\n                \"(?x)\\n  (?<=[({\\\\[,?=>:*]|&&|\\\\|\\\\||\\\\?|\\\\Wreturn|^return|\\\\Wdefault|^)\\\\s*\\n  (?!<\\\\s*[_$[:alpha:]][_$[:alnum:]]*((\\\\s+extends\\\\s+[^=>])|,)) # look ahead is not type parameter of arrow\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(/>)|(?:(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\\\s*(>))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.tag.js.jsx\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.tag.begin.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"support.class.component.js.jsx\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag\"\n                }\n            ]\n        },\n        \"jsx-child-tag\": {\n            \"begin\":\n                \"(?x)\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(/>)|(?:(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\\\s*(>))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.tag.js.jsx\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.tag.begin.js.jsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.js.jsx\"\n                },\n                \"4\": {\n                    \"name\": \"support.class.component.js.jsx\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag\"\n                }\n            ]\n        },\n        \"jsx-tag\": {\n            \"name\": \"meta.tag.js.jsx\",\n            \"begin\":\n                \"(?x)\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(?=(/>)|(?:(</)\\\\s*([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\\\s*(>)))\",\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?x)\\n  (<)\\\\s*\\n  ((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.begin.js.jsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.class.component.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=[/]?>)\",\n                    \"contentName\": \"meta.tag.attributes.js.jsx\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#jsx-tag-attributes\"\n                        },\n                        {\n                            \"include\": \"#jsx-tag-attributes-illegal\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.js.jsx\"\n                        }\n                    },\n                    \"end\": \"(?=</)\",\n                    \"contentName\": \"meta.jsx.children.js.jsx\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsx-children\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsx-children\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes\"\n                },\n                {\n                    \"include\": \"#jsx-child-tag\"\n                },\n                {\n                    \"include\": \"#jsx-evaluated-code\"\n                },\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-evaluated-code\": {\n            \"name\": \"meta.embedded.expression.js.jsx\",\n            \"begin\": \"\\\\{\",\n            \"end\": \"\\\\}\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.begin.js.jsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"jsx-entities\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.entity.js.jsx\",\n                    \"match\": \"(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.js.jsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.entity.js.jsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"invalid.illegal.bad-ampersand.js.jsx\",\n                    \"match\": \"&\"\n                }\n            ]\n        },\n        \"jsx-tag-attributes\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-attribute-name\"\n                },\n                {\n                    \"include\": \"#jsx-tag-attribute-assignment\"\n                },\n                {\n                    \"include\": \"#jsx-string-double-quoted\"\n                },\n                {\n                    \"include\": \"#jsx-string-single-quoted\"\n                },\n                {\n                    \"include\": \"#jsx-evaluated-code\"\n                }\n            ]\n        },\n        \"jsx-tag-attribute-name\": {\n            \"match\": \"(?x)\\n  \\\\s*\\n  ([_$a-zA-Z][-$\\\\w]*)\\n  (?=\\\\s|=|/?>|/\\\\*|//)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.js.jsx\"\n                }\n            }\n        },\n        \"jsx-tag-attribute-assignment\": {\n            \"name\": \"keyword.operator.assignment.js.jsx\",\n            \"match\": \"=(?=\\\\s*(?:'|\\\"|{|/\\\\*|//|\\\\n))\"\n        },\n        \"jsx-string-double-quoted\": {\n            \"name\": \"string.quoted.double.js.jsx\",\n            \"begin\": \"\\\"\",\n            \"end\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js.jsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-string-single-quoted\": {\n            \"name\": \"string.quoted.single.js.jsx\",\n            \"begin\": \"'\",\n            \"end\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.js.jsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.js.jsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-tag-attributes-illegal\": {\n            \"name\": \"invalid.illegal.attribute.js.jsx\",\n            \"match\": \"\\\\S+\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/less/syntaxes/less.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-less/blob/master/grammars/less.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-less/commit/b5b3438916bd617fe2b61e090b438c3e27034fc1\",\n    \"name\": \"Less\",\n    \"scopeName\": \"source.css.less\",\n    \"fileTypes\": [\"less\", \"less.erb\", \"rc\", \"gtkrc\", \"gtkrc-2.0\", \"themerc\"],\n    \"patterns\": [\n        {\n            \"include\": \"#strings\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.class.mixin.css\"\n                }\n            },\n            \"match\": \"(\\\\.[_a-zA-Z][a-zA-Z0-9_-]*(?=\\\\())\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.class.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"4\": {\n                    \"name\": \"variable.other.interpolation.less\"\n                }\n            },\n            \"match\": \"((\\\\.)([_a-zA-Z]|(@{[a-zA-Z0-9_-]+}))[a-zA-Z0-9_-]*)\"\n        },\n        {\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"entity.other.attribute-name.parent-selector.css\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                }\n            },\n            \"match\": \"(&)[a-zA-Z0-9_-]*\"\n        },\n        {\n            \"begin\": \"(format|local|url|attr|counter|counters)\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"support.function.misc.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.function.css\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.function.css\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.css\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.css\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\.\",\n                            \"name\": \"constant.character.escape.css\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\"\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.css\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.css\"\n                        }\n                    },\n                    \"name\": \"string.quoted.double.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\(\\\\d{1,6}|.)\",\n                            \"name\": \"constant.character.escape.css\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"[^'\\\") \\\\t]+\",\n                    \"name\": \"variable.parameter.misc.css\"\n                }\n            ]\n        },\n        {\n            \"match\": \"(#)([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\\\\b(?!.*?(?<!@){)\",\n            \"name\": \"constant.other.rgb-value.css\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.id\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"4\": {\n                    \"name\": \"variable.other.interpolation.less\"\n                }\n            },\n            \"match\": \"((#)([_a-zA-Z]|(@{[a-zA-Z0-9_-]+}))[a-zA-Z0-9_-]*)\",\n            \"name\": \"meta.selector.css\"\n        },\n        {\n            \"begin\": \"/\\\\*\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.begin.css\"\n                }\n            },\n            \"end\": \"\\\\*/\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.end.css\"\n                }\n            },\n            \"name\": \"comment.block.css\"\n        },\n        {\n            \"include\": \"source.css#numeric-values\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.begin.entity.css\"\n                },\n                \"2\": {\n                    \"name\": \"entity.other.attribute-name.attribute.css\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.separator.operator.css\"\n                },\n                \"4\": {\n                    \"name\": \"string.unquoted.attribute-value.css\"\n                },\n                \"5\": {\n                    \"name\": \"string.quoted.double.attribute-value.css\"\n                },\n                \"6\": {\n                    \"name\": \"punctuation.definition.string.begin.css\"\n                },\n                \"7\": {\n                    \"name\": \"punctuation.definition.string.end.css\"\n                },\n                \"8\": {\n                    \"name\": \"punctuation.definition.end.entity.css\"\n                }\n            },\n            \"match\":\n                \"(?i)(\\\\[)\\\\s*(-?[_a-z\\\\\\\\[[:^ascii:]]][_a-z0-9\\\\-\\\\\\\\[[:^ascii:]]]*)(?:\\\\s*([~|^$*]?=)\\\\s*(?:(-?[_a-z\\\\\\\\[[:^ascii:]]][_a-z0-9\\\\-\\\\\\\\[[:^ascii:]]]*)|((?>(['\\\"])(?:[^\\\\\\\\]|\\\\\\\\.)*?(\\\\6)))))?\\\\s*(\\\\])\",\n            \"name\": \"meta.attribute-selector.css\"\n        },\n        {\n            \"begin\": \"((@)import\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.import.less\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.less\"\n                }\n            },\n            \"end\": \";\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.terminator.rule.css\"\n                }\n            },\n            \"name\": \"meta.at-rule.import.css\",\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<=\\\\(|,|\\\\s)\\\\b(reference|optional|once|multiple|less|inline)\\\\b(?=\\\\)|,)\",\n                    \"name\": \"keyword.control.import.option.less\"\n                },\n                {\n                    \"include\": \"#brace_round\"\n                },\n                {\n                    \"include\": \"source.css#commas\"\n                },\n                {\n                    \"include\": \"#strings\"\n                }\n            ]\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.fontface.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.css\"\n                }\n            },\n            \"match\": \"^\\\\s*((@)font-face\\\\b)\",\n            \"name\": \"meta.at-rule.fontface.css\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.media.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.css\"\n                }\n            },\n            \"match\": \"^\\\\s*((@)media\\\\b)\",\n            \"name\": \"meta.at-rule.media.css\"\n        },\n        {\n            \"include\": \"source.css#media-features\"\n        },\n        {\n            \"match\": \"\\\\b(tv|tty|screen|projection|print|handheld|embossed|braille|aural|all)\\\\b\",\n            \"name\": \"support.constant.media-type.media.css\"\n        },\n        {\n            \"match\": \"\\\\b(portrait|landscape)\\\\b\",\n            \"name\": \"support.constant.property-value.media-property.media.css\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"support.function.less\"\n                }\n            },\n            \"match\": \"(\\\\.[a-zA-Z0-9_-]+)\\\\s*(;|\\\\()\"\n        },\n        {\n            \"begin\": \"(^[ \\\\t]+)?(?=//)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.comment.leading.less\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"//\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.less\"\n                        }\n                    },\n                    \"end\": \"\\\\n\",\n                    \"name\": \"comment.line.double-slash.less\"\n                }\n            ]\n        },\n        {\n            \"match\": \"(@|\\\\-\\\\-)[\\\\w-]+(?=\\\\s*)\",\n            \"name\": \"variable.other.less\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.less\"\n                }\n            }\n        },\n        {\n            \"include\": \"#variable_interpolation\"\n        },\n        {\n            \"begin\": \"{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.property-list.begin.bracket.curly.css\"\n                }\n            },\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.property-list.end.bracket.curly.css\"\n                }\n            },\n            \"name\": \"meta.property-list.css\",\n            \"patterns\": [\n                {\n                    \"include\": \"source.css#pseudo-elements\"\n                },\n                {\n                    \"include\": \"source.css#pseudo-classes\"\n                },\n                {\n                    \"include\": \"source.css#tag-names\"\n                },\n                {\n                    \"include\": \"source.css#commas\"\n                },\n                {\n                    \"include\": \"#variable_interpolation\"\n                },\n                {\n                    \"include\": \"source.css#property-names\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"match\": \"\\\\!\\\\s*important\",\n            \"name\": \"keyword.other.important.css\"\n        },\n        {\n            \"match\": \"\\\\*|\\\\/|\\\\-|\\\\+|~|=|<=|>=|<|>\",\n            \"name\": \"keyword.operator.less\"\n        },\n        {\n            \"match\": \"\\\\b(not|and|when)\\\\b\",\n            \"name\": \"keyword.control.logical.operator.less\"\n        },\n        {\n            \"include\": \"source.css#tag-names\"\n        },\n        {\n            \"match\": \"(?<![\\\\w-])[a-z][\\\\w&&[^A-Z]]*+-[\\\\w-&&[^A-Z]]+\",\n            \"name\": \"entity.name.tag.custom.css\"\n        },\n        {\n            \"include\": \"source.css#pseudo-elements\"\n        },\n        {\n            \"include\": \"source.css#pseudo-classes\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.property-list.begin.css\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.property-list.end.css\"\n                }\n            },\n            \"match\": \"(\\\\{)(\\\\})\",\n            \"name\": \"meta.brace.curly.css\"\n        },\n        {\n            \"match\": \"\\\\{|\\\\}\",\n            \"name\": \"meta.brace.curly.css\"\n        },\n        {\n            \"include\": \"#brace_round\"\n        },\n        {\n            \"match\": \"\\\\[|\\\\]\",\n            \"name\": \"meta.brace.square.less\"\n        },\n        {\n            \"match\": \";\",\n            \"name\": \"punctuation.terminator.rule.css\"\n        },\n        {\n            \"match\": \":\",\n            \"name\": \"punctuation.separator.key-value.css\"\n        },\n        {\n            \"match\": \"\\\\btrue\\\\b\",\n            \"name\": \"constant.language.boolean.less\"\n        },\n        {\n            \"match\": \"\\\\bdefault\\\\b\",\n            \"name\": \"support.function.default.less\"\n        },\n        {\n            \"match\": \"\\\\b(isurl|isstring|isnumber|iskeyword|iscolor)\\\\b\",\n            \"name\": \"support.function.type-checking.less\"\n        },\n        {\n            \"match\": \"\\\\b(isunit|ispixel|ispercentage|isem)\\\\b\",\n            \"name\": \"support.function.unit-checking.less\"\n        },\n        {\n            \"include\": \"source.css#property-keywords\"\n        },\n        {\n            \"include\": \"source.css#color-keywords\"\n        },\n        {\n            \"include\": \"source.css#commas\"\n        },\n        {\n            \"include\": \"#less_builtin_functions\"\n        },\n        {\n            \"include\": \"source.css#functions\"\n        }\n    ],\n    \"repository\": {\n        \"variable_interpolation\": {\n            \"match\": \"@{[a-zA-Z0-9_-]+}\",\n            \"name\": \"variable.other.interpolation.less\"\n        },\n        \"strings\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\"\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.css\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.css\"\n                        }\n                    },\n                    \"name\": \"string.quoted.double.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\([0-9A-Fa-f]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.css\"\n                        },\n                        {\n                            \"include\": \"#variable_interpolation\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.css\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.css\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.css\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\([0-9A-Fa-f]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.css\"\n                        },\n                        {\n                            \"include\": \"#variable_interpolation\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"brace_round\": {\n            \"match\": \"\\\\(|\\\\)\",\n            \"name\": \"meta.brace.round.css\"\n        },\n        \"property_values\": {\n            \"begin\": \"(?<!&)(:)\\\\s*(?!(\\\\s*{))(?!.*(?<!@){)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.key-value.css\"\n                }\n            },\n            \"end\": \"\\\\s*(;)|\\\\s*(?=})\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.terminator.rule.css\"\n                }\n            },\n            \"contentName\": \"meta.property-value.css\",\n            \"patterns\": [\n                {\n                    \"begin\": \"url(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.brace.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.css\"\n                        }\n                    },\n                    \"name\": \"support.function.any-method.builtin.url.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#strings\"\n                        },\n                        {\n                            \"match\": \"(\\\\b|\\\\.{0,2}/)[^)]*\\\\b\",\n                            \"name\": \"string.url.css\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"source.css#property-keywords\"\n                },\n                {\n                    \"include\": \"source.css#color-keywords\"\n                },\n                {\n                    \"include\": \"source.css#commas\"\n                },\n                {\n                    \"include\": \"#less_builtin_functions\"\n                },\n                {\n                    \"include\": \"source.css#functions\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"less_builtin_functions\": {\n            \"match\":\n                \"\\\\b(abs|acos|alpha|argb|asin|atan|average|blue|calc|ceil|color|contrast|convert|convert|cos|darken|data-uri|desaturate|difference|e|escape|exclusion|extract|fade|fadein|fadeout|floor|format|green|greyscale|hardlight|hsl|hsla|hsv|hsva|hsvhue|hsvsaturation|hsvvalue|hue|length|lighten|lightness|luma|max|min|mix|mod|multiply|negation|overlay|percentage|pi|pow|red|replace|round|saturate|saturation|screen|sin|softlight|spin|sqrt|tan|unit)\\\\b\",\n            \"name\": \"support.function.any-method.builtin.less\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/lua/syntaxes/lua.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/textmate/lua.tmbundle/blob/master/Syntaxes/Lua.plist\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/textmate/lua.tmbundle/commit/42da2c6ff5d86c068f72520f856190f413911a80\",\n    \"name\": \"Lua\",\n    \"scopeName\": \"source.lua\",\n    \"comment\": \"Lua Syntax: version 0.8\",\n    \"patterns\": [\n        {\n            \"begin\":\n                \"\\\\b((local\\\\b)\\\\s+)?(function)\\\\s*(\\\\s+[a-zA-Z_][a-zA-Z0-9_]*(\\\\.[a-zA-Z_][a-zA-Z0-9_]*)*(:[a-zA-Z_][a-zA-Z0-9_]*)?\\\\s*)?(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.local.lua\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.control.lua\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.function.lua\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.parameters.begin.lua\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.lua\"\n                }\n            },\n            \"name\": \"meta.function.lua\",\n            \"patterns\": [\n                {\n                    \"match\": \"[a-zA-Z_][a-zA-Z0-9_]*\",\n                    \"name\": \"variable.parameter.function.lua\"\n                }\n            ]\n        },\n        {\n            \"match\": \"(?<![\\\\w\\\\d.])0[xX][0-9A-Fa-f]+(?![pPeE.0-9])\",\n            \"name\": \"constant.numeric.integer.hexadecimal.lua\"\n        },\n        {\n            \"match\":\n                \"(?<![\\\\w\\\\d.])0[xX][0-9A-Fa-f]+(\\\\.[0-9A-Fa-f]+)?([eE]-?\\\\d*)?([pP][-+]\\\\d+)?\",\n            \"name\": \"constant.numeric.float.hexadecimal.lua\"\n        },\n        {\n            \"match\": \"(?<![\\\\w\\\\d.])\\\\d+(?![pPeE.0-9])\",\n            \"name\": \"constant.numeric.integer.lua\"\n        },\n        {\n            \"match\": \"(?<![\\\\w\\\\d.])\\\\d+(\\\\.\\\\d+)?([eE]-?\\\\d*)?\",\n            \"name\": \"constant.numeric.float.lua\"\n        },\n        {\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.lua\"\n                }\n            },\n            \"end\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.lua\"\n                }\n            },\n            \"name\": \"string.quoted.single.lua\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.lua\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.lua\"\n                }\n            },\n            \"name\": \"string.quoted.double.lua\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?<=\\\\.cdef)\\\\s*(\\\\[(=*)\\\\[)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"string.quoted.other.multiline.lua\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.begin.lua\"\n                }\n            },\n            \"contentName\": \"meta.embedded.lua\",\n            \"end\": \"(\\\\]\\\\2\\\\])\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"string.quoted.other.multiline.lua\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.lua\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"source.c\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?<!--)\\\\[(=*)\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.lua\"\n                }\n            },\n            \"end\": \"\\\\]\\\\1\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.lua\"\n                }\n            },\n            \"name\": \"string.quoted.other.multiline.lua\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.lua\"\n                }\n            },\n            \"match\": \"\\\\A(#!).*$\\\\n?\",\n            \"name\": \"comment.line.shebang.lua\"\n        },\n        {\n            \"begin\": \"(^[ \\\\t]+)?(?=--)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.comment.leading.lua\"\n                }\n            },\n            \"end\": \"(?!\\\\G)((?!^)[ \\\\t]+\\\\n)?\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.comment.trailing.lua\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"--\\\\[(=*)\\\\[\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.begin.lua\"\n                        }\n                    },\n                    \"end\": \"\\\\]\\\\1\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.end.lua\"\n                        }\n                    },\n                    \"name\": \"comment.block.lua\"\n                },\n                {\n                    \"begin\": \"--\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.lua\"\n                        }\n                    },\n                    \"end\": \"\\\\n\",\n                    \"name\": \"comment.line.double-dash.lua\"\n                }\n            ]\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.goto.lua\"\n                },\n                \"2\": {\n                    \"name\": \"constant.other.placeholder.lua\"\n                }\n            },\n            \"match\": \"\\\\b(goto)\\\\s+([a-zA-Z_][a-zA-Z0-9_]*)\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.label.begin.lua\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.label.end.lua\"\n                }\n            },\n            \"match\": \"(::)[a-zA-Z_][a-zA-Z0-9_]*(::)\",\n            \"name\": \"constant.other.placeholder.lua\"\n        },\n        {\n            \"match\":\n                \"\\\\b(break|do|else|for|if|elseif|goto|return|then|repeat|while|until|end|function|local|in)\\\\b\",\n            \"name\": \"keyword.control.lua\"\n        },\n        {\n            \"match\":\n                \"(?<![^.]\\\\.|:)\\\\b(false|nil|true|_G|_VERSION|math\\\\.(pi|huge))\\\\b|(?<![.])\\\\.{3}(?!\\\\.)\",\n            \"name\": \"constant.language.lua\"\n        },\n        {\n            \"match\": \"(?<![^.]\\\\.|:)\\\\b(self)\\\\b\",\n            \"name\": \"variable.language.self.lua\"\n        },\n        {\n            \"match\":\n                \"(?<![^.]\\\\.|:)\\\\b(assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|loadfile|loadstring|module|next|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)\\\\b(?=\\\\s*(?:[({\\\"']|\\\\[\\\\[))\",\n            \"name\": \"support.function.lua\"\n        },\n        {\n            \"match\":\n                \"(?<![^.]\\\\.|:)\\\\b(coroutine\\\\.(create|resume|running|status|wrap|yield)|string\\\\.(byte|char|dump|find|format|gmatch|gsub|len|lower|match|rep|reverse|sub|upper)|table\\\\.(concat|insert|maxn|remove|sort)|math\\\\.(abs|acos|asin|atan2?|ceil|cosh?|deg|exp|floor|fmod|frexp|ldexp|log|log10|max|min|modf|pow|rad|random|randomseed|sinh?|sqrt|tanh?)|io\\\\.(close|flush|input|lines|open|output|popen|read|tmpfile|type|write)|os\\\\.(clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)|package\\\\.(cpath|loaded|loadlib|path|preload|seeall)|debug\\\\.(debug|[gs]etfenv|[gs]ethook|getinfo|[gs]etlocal|[gs]etmetatable|getregistry|[gs]etupvalue|traceback))\\\\b(?=\\\\s*(?:[({\\\"']|\\\\[\\\\[))\",\n            \"name\": \"support.function.library.lua\"\n        },\n        {\n            \"match\": \"\\\\b(and|or|not)\\\\b\",\n            \"name\": \"keyword.operator.lua\"\n        },\n        {\n            \"match\": \"\\\\b([a-zA-Z_][a-zA-Z0-9_]*)\\\\b(?=\\\\s*(?:[({\\\"']|\\\\[\\\\[))\",\n            \"name\": \"support.function.any-method.lua\"\n        },\n        {\n            \"match\": \"(?<=[^.]\\\\.|:)\\\\b([a-zA-Z_][a-zA-Z0-9_]*)\",\n            \"name\": \"variable.other.lua\"\n        },\n        {\n            \"match\": \"\\\\+|-|%|#|\\\\*|\\\\/|\\\\^|==?|~=|<=?|>=?|(?<!\\\\.)\\\\.{2}(?!\\\\.)\",\n            \"name\": \"keyword.operator.lua\"\n        }\n    ],\n    \"repository\": {\n        \"escaped_char\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\[abfnrtvz\\\\\\\\\\\"'\\\\n]\",\n                    \"name\": \"constant.character.escape.lua\"\n                },\n                {\n                    \"match\": \"\\\\\\\\\\\\d{1,3}\",\n                    \"name\": \"constant.character.escape.byte.lua\"\n                },\n                {\n                    \"match\": \"\\\\\\\\x[0-9A-Fa-f][0-9A-Fa-f]\",\n                    \"name\": \"constant.character.escape.byte.lua\"\n                },\n                {\n                    \"match\": \"\\\\\\\\u\\\\{[0-9A-Fa-f]+\\\\}\",\n                    \"name\": \"constant.character.escape.unicode.lua\"\n                },\n                {\n                    \"match\": \"\\\\\\\\.\",\n                    \"name\": \"invalid.illegal.character.escape.lua\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/markdown/syntaxes/markdown.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/microsoft/vscode-markdown-tm-grammar/blob/master/syntaxes/markdown.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/microsoft/vscode-markdown-tm-grammar/commit/6e1063a71d4d017f976ccbe3d68138f4662c9a66\",\n    \"name\": \"Markdown\",\n    \"scopeName\": \"text.html.markdown\",\n    \"patterns\": [\n        {\n            \"include\": \"#frontMatter\"\n        },\n        {\n            \"include\": \"#block\"\n        }\n    ],\n    \"repository\": {\n        \"block\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#separator\"\n                },\n                {\n                    \"include\": \"#heading\"\n                },\n                {\n                    \"include\": \"#blockquote\"\n                },\n                {\n                    \"include\": \"#lists\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_css\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_basic\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_ini\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_java\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_lua\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_makefile\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_perl\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_r\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_ruby\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_php\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_sql\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_vs_net\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_xml\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_xsl\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_yaml\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_dosbatch\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_clojure\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_coffee\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_c\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_cpp\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_diff\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_dockerfile\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_git_commit\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_git_rebase\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_go\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_groovy\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_jade\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_js\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_js_regexp\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_json\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_less\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_objc\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_scss\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_perl6\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_powershell\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_python\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_regexp_python\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_rust\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_scala\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_shell\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_ts\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_tsx\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_csharp\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_fsharp\"\n                },\n                {\n                    \"include\": \"#fenced_code_block_unknown\"\n                },\n                {\n                    \"include\": \"#raw_block\"\n                },\n                {\n                    \"include\": \"#link-def\"\n                },\n                {\n                    \"include\": \"#html\"\n                },\n                {\n                    \"include\": \"#paragraph\"\n                }\n            ],\n            \"repository\": {\n                \"blockquote\": {\n                    \"begin\": \"(^|\\\\G)[ ]{0,3}(>) ?\",\n                    \"captures\": {\n                        \"2\": {\n                            \"name\": \"beginning.punctuation.definition.quote.markdown\"\n                        }\n                    },\n                    \"name\": \"markup.quote.markdown\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#block\"\n                        }\n                    ],\n                    \"while\": \"(^|\\\\G)\\\\s*(>) ?\"\n                },\n                \"fenced_code_block_css\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(css|css.erb)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.css\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.css\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_basic\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(html|htm|shtml|xhtml|inc|tmpl|tpl)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.html\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.html.basic\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_ini\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(ini|conf)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.ini\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.ini\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_java\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(java|bsh)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.java\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.java\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_lua\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(lua)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.lua\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.lua\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_makefile\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(Makefile|makefile|GNUmakefile|OCamlMakefile)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.makefile\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.makefile\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_perl\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(perl|pl|pm|pod|t|PL|psgi|vcl)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.perl\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.perl\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_r\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(R|r|s|S|Rprofile)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.r\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.r\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_ruby\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(ruby|rb|rbx|rjs|Rakefile|rake|cgi|fcgi|gemspec|irbrc|Capfile|ru|prawn|Cheffile|Gemfile|Guardfile|Hobofile|Vagrantfile|Appraisals|Rantfile|Berksfile|Berksfile.lock|Thorfile|Puppetfile)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.ruby\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.ruby\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_php\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(php|php3|php4|php5|phpt|phtml|aw|ctp)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.php\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.html.basic\"\n                                },\n                                {\n                                    \"include\": \"source.php\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_sql\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(sql|ddl|dml)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.sql\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.sql\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_vs_net\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(vb)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.vs_net\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.asp.vb.net\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_xml\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(xml|xsd|tld|jsp|pt|cpt|dtml|rss|opml)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.xml\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.xml\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_xsl\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(xsl|xslt)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.xsl\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.xml.xsl\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_yaml\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(yaml|yml)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.yaml\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.yaml\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_dosbatch\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(bat|batch)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.dosbatch\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.dosbatch\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_clojure\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(clj|cljs|clojure)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.clojure\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.clojure\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_coffee\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(coffee|Cakefile|coffee.erb)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.coffee\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.coffee\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_c\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(c|h)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.c\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.c\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_cpp\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(cpp|c\\\\+\\\\+|cxx)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.cpp\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.cpp\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_diff\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(patch|diff|rej)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.diff\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.diff\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_dockerfile\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(dockerfile|Dockerfile)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.dockerfile\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.dockerfile\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_git_commit\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(COMMIT_EDITMSG|MERGE_MSG)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.git_commit\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.git-commit\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_git_rebase\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(git-rebase-todo)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.git_rebase\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.git-rebase\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_go\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(go|golang)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.go\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.go\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_groovy\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(groovy|gvy)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.groovy\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.groovy\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_jade\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(jade|pug)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.jade\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.jade\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_js\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(js|jsx|javascript|es6|mjs)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.javascript\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.js\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_js_regexp\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(regexp)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.js_regexp\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.js.regexp\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_json\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(json|sublime-settings|sublime-menu|sublime-keymap|sublime-mousemap|sublime-theme|sublime-build|sublime-project|sublime-completions)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.json\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.json\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_less\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(less)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.less\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.css.less\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_objc\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(objectivec|objective-c|mm|objc|obj-c|m|h)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.objc\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.objc\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_scss\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(scss)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.scss\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.css.scss\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_perl6\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(perl6|p6|pl6|pm6|nqp)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.perl6\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.perl.6\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_powershell\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(powershell|ps1|psm1|psd1)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.powershell\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.powershell\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_python\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(python|py|py3|rpy|pyw|cpy|SConstruct|Sconstruct|sconstruct|SConscript|gyp|gypi)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.python\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.python\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_regexp_python\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(re)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.regexp_python\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.regexp.python\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_rust\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(rust|rs)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.rust\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.rust\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_scala\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(scala|sbt)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.scala\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.scala\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_shell\": {\n                    \"begin\":\n                        \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(shell|sh|bash|zsh|bashrc|bash_profile|bash_login|profile|bash_logout|.textmate_init)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.shellscript\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.shell\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_ts\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(typescript|ts)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.typescript\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.ts\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_tsx\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(tsx)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.typescriptreact\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.tsx\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_csharp\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(cs|csharp|c#)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.csharp\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.cs\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_fsharp\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?i:(fs|fsharp|f#)(\\\\s+[^`~]*)?$)\",\n                    \"name\": \"markup.fenced_code.block.markdown\",\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"fenced_code.block.language\"\n                        },\n                        \"6\": {\n                            \"name\": \"fenced_code.block.language.attributes\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)(\\\\s*)(.*)\",\n                            \"while\": \"(^|\\\\G)(?!\\\\s*([`~]{3,})\\\\s*$)\",\n                            \"contentName\": \"meta.embedded.block.fsharp\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"source.fsharp\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                \"fenced_code_block_unknown\": {\n                    \"begin\": \"(^|\\\\G)(\\\\s*)(`{3,}|~{3,})\\\\s*(?=([^`~]*)?$)\",\n                    \"beginCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"fenced_code.block.language\"\n                        }\n                    },\n                    \"end\": \"(^|\\\\G)(\\\\2|\\\\s{0,3})(\\\\3)\\\\s*$\",\n                    \"endCaptures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.markdown\"\n                        }\n                    },\n                    \"name\": \"markup.fenced_code.block.markdown\"\n                },\n                \"heading\": {\n                    \"begin\": \"(?:^|\\\\G)[ ]{0,3}(#{1,6})\\\\s*(?=[\\\\S[^#]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.heading.markdown\"\n                        }\n                    },\n                    \"contentName\": \"entity.name.section.markdown\",\n                    \"end\": \"\\\\s*(#{1,6})?$\\\\n?\",\n                    \"name\": \"markup.heading.markdown\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#inline\"\n                        }\n                    ]\n                },\n                \"heading-setext\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"^(={3,})(?=[ \\\\t]*$\\\\n?)\",\n                            \"name\": \"markup.heading.setext.1.markdown\"\n                        },\n                        {\n                            \"match\": \"^(-{3,})(?=[ \\\\t]*$\\\\n?)\",\n                            \"name\": \"markup.heading.setext.2.markdown\"\n                        }\n                    ]\n                },\n                \"html\": {\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)\\\\s*(<!--)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.comment.html\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.comment.html\"\n                                }\n                            },\n                            \"end\": \"(-->)\",\n                            \"name\": \"comment.block.html\"\n                        },\n                        {\n                            \"begin\":\n                                \"(^|\\\\G)\\\\s*(?=<(script|style|pre)(\\\\s|$|>)(?!.*?</(script|style|pre)>))\",\n                            \"end\": \"(?=.*</(script|style|pre)>)\",\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"(\\\\s*|$)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"text.html.basic\"\n                                        }\n                                    ],\n                                    \"while\": \"^(?!.*</(script|style|pre)>)\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\":\n                                \"(^|\\\\G)\\\\s*(?=</?(address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h1|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(\\\\s|$|/?>))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.html.basic\"\n                                }\n                            ],\n                            \"while\": \"^(?!\\\\s*$)\"\n                        },\n                        {\n                            \"begin\":\n                                \"(^|\\\\G)\\\\s*(?=(<[a-zA-Z0-9\\\\-](/?>|\\\\s.*?>)|</[a-zA-Z0-9\\\\-]>)\\\\s*$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.html.basic\"\n                                }\n                            ],\n                            \"while\": \"^(?!\\\\s*$)\"\n                        }\n                    ]\n                },\n                \"link-def\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.constant.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.other.reference.link.markdown\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.constant.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.separator.key-value.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"6\": {\n                            \"name\": \"markup.underline.link.markdown\"\n                        },\n                        \"7\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"8\": {\n                            \"name\": \"string.other.link.description.title.markdown\"\n                        },\n                        \"9\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"10\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"11\": {\n                            \"name\": \"string.other.link.description.title.markdown\"\n                        },\n                        \"12\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"13\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        }\n                    },\n                    \"match\":\n                        \"(?x)\\n  \\\\s*            # Leading whitespace\\n  (\\\\[)(.+?)(\\\\])(:)    # Reference name\\n  [ \\\\t]*          # Optional whitespace\\n  (<?)(\\\\S+?)(>?)      # The url\\n  [ \\\\t]*          # Optional whitespace\\n  (?:\\n      ((\\\\().+?(\\\\)))    # Match title in quotes…\\n    | ((\\\").+?(\\\"))    # or in parens.\\n  )?            # Title is optional\\n  \\\\s*            # Optional whitespace\\n  $\\n\",\n                    \"name\": \"meta.link.reference.def.markdown\"\n                },\n                \"list_paragraph\": {\n                    \"begin\": \"(^|\\\\G)(?=\\\\S)(?![*+->]\\\\s|[0-9]+\\\\.\\\\s)\",\n                    \"name\": \"meta.paragraph.markdown\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#inline\"\n                        },\n                        {\n                            \"include\": \"text.html.basic\"\n                        },\n                        {\n                            \"include\": \"#heading-setext\"\n                        }\n                    ],\n                    \"while\":\n                        \"(^|\\\\G)(?!\\\\s*$|#|[ ]{0,3}([-*_>][ ]{2,}){3,}[ \\\\t]*$\\\\n?|[ ]{0,3}[*+->]|[ ]{0,3}[0-9]+\\\\.)\"\n                },\n                \"lists\": {\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(^|\\\\G)([ ]{0,3})([*+-])([ ]{1,3}|\\\\t)\",\n                            \"beginCaptures\": {\n                                \"3\": {\n                                    \"name\": \"beginning.punctuation.definition.list.markdown\"\n                                }\n                            },\n                            \"comment\": \"Currently does not support un-indented second lines.\",\n                            \"name\": \"markup.list.unnumbered.markdown\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#block\"\n                                },\n                                {\n                                    \"include\": \"#list_paragraph\"\n                                }\n                            ],\n                            \"while\": \"((^|\\\\G)([ ]{4}|\\\\t))|(^[ \\\\t]*$)\"\n                        },\n                        {\n                            \"begin\": \"(^|\\\\G)([ ]{0,3})([0-9]+\\\\.)([ ]{1,3}|\\\\t)\",\n                            \"beginCaptures\": {\n                                \"3\": {\n                                    \"name\": \"beginning.punctuation.definition.list.markdown\"\n                                }\n                            },\n                            \"name\": \"markup.list.numbered.markdown\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#block\"\n                                },\n                                {\n                                    \"include\": \"#list_paragraph\"\n                                }\n                            ],\n                            \"while\": \"((^|\\\\G)([ ]{4}|\\\\t))|(^[ \\\\t]*$)\"\n                        }\n                    ]\n                },\n                \"paragraph\": {\n                    \"begin\": \"(^|\\\\G)[ ]{0,3}(?=\\\\S)\",\n                    \"name\": \"meta.paragraph.markdown\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#inline\"\n                        },\n                        {\n                            \"include\": \"text.html.basic\"\n                        },\n                        {\n                            \"include\": \"#heading-setext\"\n                        }\n                    ],\n                    \"while\": \"(^|\\\\G)((?=\\\\s*[-=]{3,}\\\\s*$)|[ ]{4,}(?=\\\\S))\"\n                },\n                \"raw_block\": {\n                    \"begin\": \"(^|\\\\G)([ ]{4}|\\\\t)\",\n                    \"name\": \"markup.raw.block.markdown\",\n                    \"while\": \"(^|\\\\G)([ ]{4}|\\\\t)\"\n                },\n                \"separator\": {\n                    \"match\": \"(^|\\\\G)[ ]{0,3}([*-_])([ ]{0,2}\\\\2){2,}[ \\\\t]*$\\\\n?\",\n                    \"name\": \"meta.separator.markdown\"\n                }\n            }\n        },\n        \"frontMatter\": {\n            \"begin\": \"\\\\A-{3}\\\\s*$\",\n            \"contentName\": \"meta.embedded.block.frontmatter\",\n            \"patterns\": [\n                {\n                    \"include\": \"source.yaml\"\n                }\n            ],\n            \"while\": \"^(?!(-{3}|\\\\.{3})\\\\s*$)\"\n        },\n        \"inline\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#ampersand\"\n                },\n                {\n                    \"include\": \"#bracket\"\n                },\n                {\n                    \"include\": \"#bold\"\n                },\n                {\n                    \"include\": \"#italic\"\n                },\n                {\n                    \"include\": \"#raw\"\n                },\n                {\n                    \"include\": \"#escape\"\n                },\n                {\n                    \"include\": \"#image-inline\"\n                },\n                {\n                    \"include\": \"#image-ref\"\n                },\n                {\n                    \"include\": \"#link-email\"\n                },\n                {\n                    \"include\": \"#link-inet\"\n                },\n                {\n                    \"include\": \"#link-inline\"\n                },\n                {\n                    \"include\": \"#link-ref\"\n                },\n                {\n                    \"include\": \"#link-ref-literal\"\n                }\n            ],\n            \"repository\": {\n                \"ampersand\": {\n                    \"comment\":\n                        \"Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid.\",\n                    \"match\": \"&(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);)\",\n                    \"name\": \"meta.other.valid-ampersand.markdown\"\n                },\n                \"bold\": {\n                    \"begin\":\n                        \"(?x)\\n ((?<!\\\\w)\\\\*\\\\*\\\\b|\\\\b__)(?=\\\\S)                # Open\\n (?=\\n   (\\n     <[^>]*+>              # HTML tags\\n     | (?<raw>`+)([^`]|(?!(?<!`)\\\\k<raw>(?!`))`)*+\\\\k<raw>\\n                       # Raw\\n     | \\\\\\\\[\\\\\\\\`*_{}\\\\[\\\\]()#.!+\\\\->]?+      # Escapes\\n     | \\\\[\\n     (\\n         (?<square>          # Named group\\n           [^\\\\[\\\\]\\\\\\\\]        # Match most chars\\n           | \\\\\\\\.            # Escaped chars\\n           | \\\\[ \\\\g<square>*+ \\\\]    # Nested brackets\\n         )*+\\n       \\\\]\\n       (\\n         (              # Reference Link\\n           [ ]?          # Optional space\\n           \\\\[[^\\\\]]*+\\\\]        # Ref name\\n         )\\n         | (              # Inline Link\\n           \\\\(            # Opening paren\\n             [ \\\\t]*+        # Optional whitespace\\n             <?(.*?)>?      # URL\\n             [ \\\\t]*+        # Optional whitespace\\n             (          # Optional Title\\n               (?<title>['\\\"])\\n               (.*?)\\n               \\\\k<title>\\n             )?\\n           \\\\)\\n         )\\n       )\\n     )\\n     | (?!(?<=\\\\S)\\\\1).            # Everything besides\\n                       # style closer\\n   )++\\n   (?<=\\\\S)\\\\1                # Close\\n )\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bold.markdown\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\S)(\\\\1)\",\n                    \"name\": \"markup.bold.markdown\",\n                    \"patterns\": [\n                        {\n                            \"applyEndPatternLast\": 1,\n                            \"begin\": \"(?=<[^>]*?>)\",\n                            \"end\": \"(?<=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.html.basic\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#escape\"\n                        },\n                        {\n                            \"include\": \"#ampersand\"\n                        },\n                        {\n                            \"include\": \"#bracket\"\n                        },\n                        {\n                            \"include\": \"#raw\"\n                        },\n                        {\n                            \"include\": \"#bold\"\n                        },\n                        {\n                            \"include\": \"#italic\"\n                        },\n                        {\n                            \"include\": \"#image-inline\"\n                        },\n                        {\n                            \"include\": \"#link-inline\"\n                        },\n                        {\n                            \"include\": \"#link-inet\"\n                        },\n                        {\n                            \"include\": \"#link-email\"\n                        },\n                        {\n                            \"include\": \"#image-ref\"\n                        },\n                        {\n                            \"include\": \"#link-ref-literal\"\n                        },\n                        {\n                            \"include\": \"#link-ref\"\n                        }\n                    ]\n                },\n                \"bracket\": {\n                    \"comment\":\n                        \"Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid.\",\n                    \"match\": \"<(?![a-z/?\\\\$!])\",\n                    \"name\": \"meta.other.valid-bracket.markdown\"\n                },\n                \"escape\": {\n                    \"match\": \"\\\\\\\\[-`*_#+.!(){}\\\\[\\\\]\\\\\\\\>]\",\n                    \"name\": \"constant.character.escape.markdown\"\n                },\n                \"image-inline\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.other.link.description.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.metadata.markdown\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"7\": {\n                            \"name\": \"markup.underline.link.image.markdown\"\n                        },\n                        \"8\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"9\": {\n                            \"name\": \"string.other.link.description.title.markdown\"\n                        },\n                        \"10\": {\n                            \"name\": \"punctuation.definition.string.markdown\"\n                        },\n                        \"11\": {\n                            \"name\": \"punctuation.definition.string.markdown\"\n                        },\n                        \"12\": {\n                            \"name\": \"string.other.link.description.title.markdown\"\n                        },\n                        \"13\": {\n                            \"name\": \"punctuation.definition.string.markdown\"\n                        },\n                        \"14\": {\n                            \"name\": \"punctuation.definition.string.markdown\"\n                        },\n                        \"15\": {\n                            \"name\": \"punctuation.definition.metadata.markdown\"\n                        }\n                    },\n                    \"match\":\n                        \"(?x)\\n  (\\\\!\\\\[)((?<square>[^\\\\[\\\\]\\\\\\\\]|\\\\\\\\.|\\\\[\\\\g<square>*+\\\\])*+)(\\\\])\\n                # Match the link text.\\n  (\\\\()            # Opening paren for url\\n    (<?)(\\\\S+?)(>?)      # The url\\n    [ \\\\t]*          # Optional whitespace\\n    (?:\\n        ((\\\\().+?(\\\\)))    # Match title in parens…\\n      | ((\\\").+?(\\\"))    # or in quotes.\\n    )?            # Title is optional\\n    \\\\s*            # Optional whitespace\\n  (\\\\))\\n\",\n                    \"name\": \"meta.image.inline.markdown\"\n                },\n                \"image-ref\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.other.link.description.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.constant.markdown\"\n                        },\n                        \"6\": {\n                            \"name\": \"constant.other.reference.link.markdown\"\n                        },\n                        \"7\": {\n                            \"name\": \"punctuation.definition.constant.markdown\"\n                        }\n                    },\n                    \"match\":\n                        \"(\\\\!\\\\[)((?<square>[^\\\\[\\\\]\\\\\\\\]|\\\\\\\\.|\\\\[\\\\g<square>*+\\\\])*+)(\\\\])[ ]?(\\\\[)(.*?)(\\\\])\",\n                    \"name\": \"meta.image.reference.markdown\"\n                },\n                \"italic\": {\n                    \"begin\":\n                        \"(?x) (\\\\*\\\\b|\\\\b_)(?=\\\\S)                # Open\\n  (?=\\n    (\\n      <[^>]*+>              # HTML tags\\n      | (?<raw>`+)([^`]|(?!(?<!`)\\\\k<raw>(?!`))`)*+\\\\k<raw>\\n                        # Raw\\n      | \\\\\\\\[\\\\\\\\`*_{}\\\\[\\\\]()#.!+\\\\->]?+      # Escapes\\n      | \\\\[\\n      (\\n          (?<square>          # Named group\\n            [^\\\\[\\\\]\\\\\\\\]        # Match most chars\\n            | \\\\\\\\.            # Escaped chars\\n            | \\\\[ \\\\g<square>*+ \\\\]    # Nested brackets\\n          )*+\\n        \\\\]\\n        (\\n          (              # Reference Link\\n            [ ]?          # Optional space\\n            \\\\[[^\\\\]]*+\\\\]        # Ref name\\n          )\\n          | (              # Inline Link\\n            \\\\(            # Opening paren\\n              [ \\\\t]*+        # Optional whtiespace\\n              <?(.*?)>?      # URL\\n              [ \\\\t]*+        # Optional whtiespace\\n              (          # Optional Title\\n                (?<title>['\\\"])\\n                (.*?)\\n                \\\\k<title>\\n              )?\\n            \\\\)\\n          )\\n        )\\n      )\\n      | \\\\1\\\\1                # Must be bold closer\\n      | (?!(?<=\\\\S)\\\\1).            # Everything besides\\n                        # style closer\\n    )++\\n    (?<=\\\\S)\\\\1                # Close\\n  )\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.italic.markdown\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\S)(\\\\1)((?!\\\\1)|(?=\\\\1\\\\1))\",\n                    \"name\": \"markup.italic.markdown\",\n                    \"patterns\": [\n                        {\n                            \"applyEndPatternLast\": 1,\n                            \"begin\": \"(?=<[^>]*?>)\",\n                            \"end\": \"(?<=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"text.html.basic\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#escape\"\n                        },\n                        {\n                            \"include\": \"#ampersand\"\n                        },\n                        {\n                            \"include\": \"#bracket\"\n                        },\n                        {\n                            \"include\": \"#raw\"\n                        },\n                        {\n                            \"include\": \"#bold\"\n                        },\n                        {\n                            \"include\": \"#image-inline\"\n                        },\n                        {\n                            \"include\": \"#link-inline\"\n                        },\n                        {\n                            \"include\": \"#link-inet\"\n                        },\n                        {\n                            \"include\": \"#link-email\"\n                        },\n                        {\n                            \"include\": \"#image-ref\"\n                        },\n                        {\n                            \"include\": \"#link-ref-literal\"\n                        },\n                        {\n                            \"include\": \"#link-ref\"\n                        }\n                    ]\n                },\n                \"link-email\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"markup.underline.link.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        }\n                    },\n                    \"match\": \"(<)((?:mailto:)?[-.\\\\w]+@[-a-z0-9]+(\\\\.[-a-z0-9]+)*\\\\.[a-z]+)(>)\",\n                    \"name\": \"meta.link.email.lt-gt.markdown\"\n                },\n                \"link-inet\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"markup.underline.link.markdown\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        }\n                    },\n                    \"match\": \"(<)((?:https?|ftp)://.*?)(>)\",\n                    \"name\": \"meta.link.inet.markdown\"\n                },\n                \"link-inline\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.other.link.title.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.metadata.markdown\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"7\": {\n                            \"name\": \"markup.underline.link.markdown\"\n                        },\n                        \"8\": {\n                            \"name\": \"punctuation.definition.link.markdown\"\n                        },\n                        \"9\": {\n                            \"name\": \"string.other.link.description.title.markdown\"\n                        },\n                        \"10\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"11\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"12\": {\n                            \"name\": \"string.other.link.description.title.markdown\"\n                        },\n                        \"13\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"14\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"15\": {\n                            \"name\": \"punctuation.definition.metadata.markdown\"\n                        }\n                    },\n                    \"match\":\n                        \"(?x)\\n  (\\\\[)((?<square>[^\\\\[\\\\]\\\\\\\\]|\\\\\\\\.|\\\\[\\\\g<square>*+\\\\])*+)(\\\\])\\n                # Match the link text.\\n  (\\\\()            # Opening paren for url\\n    (<?)(.*?)(>?)      # The url\\n    [ \\\\t]*          # Optional whitespace\\n    (?:\\n        ((\\\\().+?(\\\\)))    # Match title in parens…\\n      | ((\\\").+?(\\\"))    # or in quotes.\\n    )?            # Title is optional\\n    \\\\s*            # Optional whitespace\\n  (\\\\))\\n\",\n                    \"name\": \"meta.link.inline.markdown\"\n                },\n                \"link-ref\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.other.link.title.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.constant.begin.markdown\"\n                        },\n                        \"6\": {\n                            \"name\": \"constant.other.reference.link.markdown\"\n                        },\n                        \"7\": {\n                            \"name\": \"punctuation.definition.constant.end.markdown\"\n                        }\n                    },\n                    \"match\":\n                        \"(\\\\[)((?<square>[^\\\\[\\\\]\\\\\\\\]|\\\\\\\\.|\\\\[\\\\g<square>*+\\\\])*+)(\\\\])(\\\\[)([^\\\\]]*+)(\\\\])\",\n                    \"name\": \"meta.link.reference.markdown\"\n                },\n                \"link-ref-literal\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.markdown\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.other.link.title.markdown\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.end.markdown\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.constant.begin.markdown\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.constant.end.markdown\"\n                        }\n                    },\n                    \"match\":\n                        \"(\\\\[)((?<square>[^\\\\[\\\\]\\\\\\\\]|\\\\\\\\.|\\\\[\\\\g<square>*+\\\\])*+)(\\\\])[ ]?(\\\\[)(\\\\])\",\n                    \"name\": \"meta.link.reference.literal.markdown\"\n                },\n                \"raw\": {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.raw.markdown\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.raw.markdown\"\n                        }\n                    },\n                    \"match\": \"(`+)([^`]|(?!(?<!`)\\\\1(?!`))`)*+(\\\\1)\",\n                    \"name\": \"markup.inline.raw.string.markdown\"\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/objective-c/syntaxes/objective-c++.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-objective-c/blob/master/grammars/objective-c%2B%2B.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-objective-c/commit/7fdf0c40ec1d592a902ed6a7cf5565bdf12e2ae8\",\n    \"name\": \"Objective-C++\",\n    \"scopeName\": \"source.objcpp\",\n    \"patterns\": [\n        {\n            \"include\": \"source.cpp\"\n        },\n        {\n            \"include\": \"source.objc\"\n        }\n    ]\n}\n"
  },
  {
    "path": "extensions/objective-c/syntaxes/objective-c.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-objective-c/blob/master/grammars/objective-c.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-objective-c/commit/0727e04544f3414c1c339cf15a39a05ea3938cb4\",\n    \"name\": \"Objective-C\",\n    \"scopeName\": \"source.objc\",\n    \"patterns\": [\n        {\n            \"begin\":\n                \"((@)(interface|protocol))(?!.+;)\\\\s+([A-Za-z_][A-Za-z0-9_]*)\\\\s*((:)(?:\\\\s*)([A-Za-z][A-Za-z0-9]*))?(\\\\s|\\\\n)?\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.objc\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.storage.type.objc\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.type.objc\"\n                },\n                \"6\": {\n                    \"name\": \"punctuation.definition.entity.other.inherited-class.objc\"\n                },\n                \"7\": {\n                    \"name\": \"entity.other.inherited-class.objc\"\n                },\n                \"8\": {\n                    \"name\": \"meta.divider.objc\"\n                },\n                \"9\": {\n                    \"name\": \"meta.inherited-class.objc\"\n                }\n            },\n            \"contentName\": \"meta.scope.interface.objc\",\n            \"end\": \"((@)end)\\\\b\",\n            \"name\": \"meta.interface-or-protocol.objc\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interface_innards\"\n                }\n            ]\n        },\n        {\n            \"begin\":\n                \"((@)(implementation))\\\\s+([A-Za-z_][A-Za-z0-9_]*)\\\\s*(?::\\\\s*([A-Za-z][A-Za-z0-9]*))?\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.objc\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.storage.type.objc\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.type.objc\"\n                },\n                \"5\": {\n                    \"name\": \"entity.other.inherited-class.objc\"\n                }\n            },\n            \"contentName\": \"meta.scope.implementation.objc\",\n            \"end\": \"((@)end)\\\\b\",\n            \"name\": \"meta.implementation.objc\",\n            \"patterns\": [\n                {\n                    \"include\": \"#implementation_innards\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"@\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.objc\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.objc\"\n                }\n            },\n            \"name\": \"string.quoted.double.objc\",\n            \"patterns\": [\n                {\n                    \"include\": \"source.c#string_escaped_char\"\n                },\n                {\n                    \"match\":\n                        \"(?x)%\\n\\t\\t\\t\\t\\t\\t(\\\\d+\\\\$)?                             # field (argument #)\\n\\t\\t\\t\\t\\t\\t[#0\\\\- +']*                          # flags\\n\\t\\t\\t\\t\\t\\t((-?\\\\d+)|\\\\*(-?\\\\d+\\\\$)?)?              # minimum field width\\n\\t\\t\\t\\t\\t\\t(\\\\.((-?\\\\d+)|\\\\*(-?\\\\d+\\\\$)?)?)?         # precision\\n\\t\\t\\t\\t\\t\\t[@]                                  # conversion type\\n\\t\\t\\t\\t\\t\",\n                    \"name\": \"constant.other.placeholder.objc\"\n                },\n                {\n                    \"include\": \"source.c#string_placeholder\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\b(id)\\\\s*(?=<)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.objc\"\n                }\n            },\n            \"end\": \"(?<=>)\",\n            \"name\": \"meta.id-with-protocol.objc\",\n            \"patterns\": [\n                {\n                    \"include\": \"#protocol_list\"\n                }\n            ]\n        },\n        {\n            \"match\": \"\\\\b(NS_DURING|NS_HANDLER|NS_ENDHANDLER)\\\\b\",\n            \"name\": \"keyword.control.macro.objc\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.objc\"\n                }\n            },\n            \"match\": \"(@)(try|catch|finally|throw)\\\\b\",\n            \"name\": \"keyword.control.exception.objc\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.objc\"\n                }\n            },\n            \"match\": \"(@)(synchronized)\\\\b\",\n            \"name\": \"keyword.control.synchronize.objc\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.objc\"\n                }\n            },\n            \"match\": \"(@)(required|optional)\\\\b\",\n            \"name\": \"keyword.control.protocol-specification.objc\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.objc\"\n                }\n            },\n            \"match\": \"(@)(defs|encode)\\\\b\",\n            \"name\": \"keyword.other.objc\"\n        },\n        {\n            \"match\": \"\\\\bid\\\\b\",\n            \"name\": \"storage.type.id.objc\"\n        },\n        {\n            \"match\": \"\\\\b(IBOutlet|IBAction|BOOL|SEL|id|unichar|IMP|Class|instancetype)\\\\b\",\n            \"name\": \"storage.type.objc\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.storage.type.objc\"\n                }\n            },\n            \"match\": \"(@)(class|protocol)\\\\b\",\n            \"name\": \"storage.type.objc\"\n        },\n        {\n            \"begin\": \"((@)selector)\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.objc\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.storage.type.objc\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.storage.type.objc\"\n                }\n            },\n            \"contentName\": \"meta.selector.method-name.objc\",\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.storage.type.objc\"\n                }\n            },\n            \"name\": \"meta.selector.objc\",\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.arguments.objc\"\n                        }\n                    },\n                    \"match\": \"\\\\b(?:[a-zA-Z_:][\\\\w]*)+\",\n                    \"name\": \"support.function.any-method.name-of-parameter.objc\"\n                }\n            ]\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.storage.modifier.objc\"\n                }\n            },\n            \"match\": \"(@)(synchronized|public|package|private|protected)\\\\b\",\n            \"name\": \"storage.modifier.objc\"\n        },\n        {\n            \"match\": \"\\\\b(YES|NO|Nil|nil)\\\\b\",\n            \"name\": \"constant.language.objc\"\n        },\n        {\n            \"match\": \"\\\\bNSApp\\\\b\",\n            \"name\": \"support.variable.foundation\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.support.function.cocoa.leopard\"\n                },\n                \"2\": {\n                    \"name\": \"support.function.cocoa.leopard\"\n                }\n            },\n            \"match\":\n                \"(\\\\s*)\\\\b(NS(Rect(ToCGRect|FromCGRect)|MakeCollectable|S(tringFromProtocol|ize(ToCGSize|FromCGSize))|Draw(NinePartImage|ThreePartImage)|P(oint(ToCGPoint|FromCGPoint)|rotocolFromString)|EventMaskFromType|Value))\\\\b\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.support.function.leading.cocoa\"\n                },\n                \"2\": {\n                    \"name\": \"support.function.cocoa\"\n                }\n            },\n            \"match\":\n                \"(\\\\s*)\\\\b(NS(R(ound(DownToMultipleOfPageSize|UpToMultipleOfPageSize)|un(CriticalAlertPanel(RelativeToWindow)?|InformationalAlertPanel(RelativeToWindow)?|AlertPanel(RelativeToWindow)?)|e(set(MapTable|HashTable)|c(ycleZone|t(Clip(List)?|F(ill(UsingOperation|List(UsingOperation|With(Grays|Colors(UsingOperation)?))?)?|romString))|ordAllocationEvent)|turnAddress|leaseAlertPanel|a(dPixel|l(MemoryAvailable|locateCollectable))|gisterServicesProvider)|angeFromString)|Get(SizeAndAlignment|CriticalAlertPanel|InformationalAlertPanel|UncaughtExceptionHandler|FileType(s)?|WindowServerMemory|AlertPanel)|M(i(n(X|Y)|d(X|Y))|ouseInRect|a(p(Remove|Get|Member|Insert(IfAbsent|KnownAbsent)?)|ke(R(ect|ange)|Size|Point)|x(Range|X|Y)))|B(itsPer(SampleFromDepth|PixelFromDepth)|e(stDepth|ep|gin(CriticalAlertSheet|InformationalAlertSheet|AlertSheet)))|S(ho(uldRetainWithZone|w(sServicesMenuItem|AnimationEffect))|tringFrom(R(ect|ange)|MapTable|S(ize|elector)|HashTable|Class|Point)|izeFromString|e(t(ShowsServicesMenuItem|ZoneName|UncaughtExceptionHandler|FocusRingStyle)|lectorFromString|archPathForDirectoriesInDomains)|wap(Big(ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(ToHost|LongToHost))|Short|Host(ShortTo(Big|Little)|IntTo(Big|Little)|DoubleTo(Big|Little)|FloatTo(Big|Little)|Long(To(Big|Little)|LongTo(Big|Little)))|Int|Double|Float|L(ittle(ShortToHost|IntToHost|DoubleToHost|FloatToHost|Long(ToHost|LongToHost))|ong(Long)?)))|H(ighlightRect|o(stByteOrder|meDirectory(ForUser)?)|eight|ash(Remove|Get|Insert(IfAbsent|KnownAbsent)?)|FSType(CodeFromFileType|OfFile))|N(umberOfColorComponents|ext(MapEnumeratorPair|HashEnumeratorItem))|C(o(n(tainsRect|vert(GlyphsToPackedGlyphs|Swapped(DoubleToHost|FloatToHost)|Host(DoubleToSwapped|FloatToSwapped)))|unt(MapTable|HashTable|Frames|Windows(ForContext)?)|py(M(emoryPages|apTableWithZone)|Bits|HashTableWithZone|Object)|lorSpaceFromDepth|mpare(MapTables|HashTables))|lassFromString|reate(MapTable(WithZone)?|HashTable(WithZone)?|Zone|File(namePboardType|ContentsPboardType)))|TemporaryDirectory|I(s(ControllerMarker|EmptyRect|FreedObject)|n(setRect|crementExtraRefCount|te(r(sect(sRect|ionR(ect|ange))|faceStyleForKey)|gralRect)))|Zone(Realloc|Malloc|Name|Calloc|Fr(omPointer|ee))|O(penStepRootDirectory|ffsetRect)|D(i(sableScreenUpdates|videRect)|ottedFrameRect|e(c(imal(Round|Multiply|S(tring|ubtract)|Normalize|Co(py|mpa(ct|re))|IsNotANumber|Divide|Power|Add)|rementExtraRefCountWasZero)|faultMallocZone|allocate(MemoryPages|Object))|raw(Gr(oove|ayBezel)|B(itmap|utton)|ColorTiledRects|TiledRects|DarkBezel|W(hiteBezel|indowBackground)|LightBezel))|U(serName|n(ionR(ect|ange)|registerServicesProvider)|pdateDynamicServices)|Java(Bundle(Setup|Cleanup)|Setup(VirtualMachine)?|Needs(ToLoadClasses|VirtualMachine)|ClassesF(orBundle|romPath)|ObjectNamedInPath|ProvidesClasses)|P(oint(InRect|FromString)|erformService|lanarFromDepth|ageSize)|E(n(d(MapTableEnumeration|HashTableEnumeration)|umerate(MapTable|HashTable)|ableScreenUpdates)|qual(R(ects|anges)|Sizes|Points)|raseRect|xtraRefCount)|F(ileTypeForHFSTypeCode|ullUserName|r(ee(MapTable|HashTable)|ame(Rect(WithWidth(UsingOperation)?)?|Address)))|Wi(ndowList(ForContext)?|dth)|Lo(cationInRange|g(v|PageSize)?)|A(ccessibility(R(oleDescription(ForUIElement)?|aiseBadArgumentException)|Unignored(Children(ForOnlyChild)?|Descendant|Ancestor)|PostNotification|ActionDescription)|pplication(Main|Load)|vailableWindowDepths|ll(MapTable(Values|Keys)|HashTableObjects|ocate(MemoryPages|Collectable|Object)))))\\\\b\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(RuleEditor|G(arbageCollector|radient)|MapTable|HashTable|Co(ndition|llectionView(Item)?)|T(oolbarItemGroup|extInputClient|r(eeNode|ackingArea))|InvocationOperation|Operation(Queue)?|D(ictionaryController|ockTile)|P(ointer(Functions|Array)|athC(o(ntrol(Delegate)?|mponentCell)|ell(Delegate)?)|r(intPanelAccessorizing|edicateEditor(RowTemplate)?))|ViewController|FastEnumeration|Animat(ionContext|ablePropertyContainer))\\\\b\",\n            \"name\": \"support.class.cocoa.leopard\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(R(u(nLoop|ler(Marker|View))|e(sponder|cursiveLock|lativeSpecifier)|an(domSpecifier|geSpecifier))|G(etCommand|lyph(Generator|Storage|Info)|raphicsContext)|XML(Node|D(ocument|TD(Node)?)|Parser|Element)|M(iddleSpecifier|ov(ie(View)?|eCommand)|utable(S(tring|et)|C(haracterSet|opying)|IndexSet|D(ictionary|ata)|URLRequest|ParagraphStyle|A(ttributedString|rray))|e(ssagePort(NameServer)?|nu(Item(Cell)?|View)?|t(hodSignature|adata(Item|Query(ResultGroup|AttributeValueTuple)?)))|a(ch(BootstrapServer|Port)|trix))|B(itmapImageRep|ox|u(ndle|tton(Cell)?)|ezierPath|rowser(Cell)?)|S(hadow|c(anner|r(ipt(SuiteRegistry|C(o(ercionHandler|mmand(Description)?)|lassDescription)|ObjectSpecifier|ExecutionContext|WhoseTest)|oll(er|View)|een))|t(epper(Cell)?|atus(Bar|Item)|r(ing|eam))|imple(HorizontalTypesetter|CString)|o(cketPort(NameServer)?|und|rtDescriptor)|p(e(cifierTest|ech(Recognizer|Synthesizer)|ll(Server|Checker))|litView)|e(cureTextField(Cell)?|t(Command)?|archField(Cell)?|rializer|gmentedC(ontrol|ell))|lider(Cell)?|avePanel)|H(ost|TTP(Cookie(Storage)?|URLResponse)|elpManager)|N(ib(Con(nector|trolConnector)|OutletConnector)?|otification(Center|Queue)?|u(ll|mber(Formatter)?)|etService(Browser)?|ameSpecifier)|C(ha(ngeSpelling|racterSet)|o(n(stantString|nection|trol(ler)?|ditionLock)|d(ing|er)|unt(Command|edSet)|pying|lor(Space|P(ick(ing(Custom|Default)|er)|anel)|Well|List)?|m(p(oundPredicate|arisonPredicate)|boBox(Cell)?))|u(stomImageRep|rsor)|IImageRep|ell|l(ipView|o(seCommand|neCommand)|assDescription)|a(ched(ImageRep|URLResponse)|lendar(Date)?)|reateCommand)|T(hread|ypesetter|ime(Zone|r)|o(olbar(Item(Validations)?)?|kenField(Cell)?)|ext(Block|Storage|Container|Tab(le(Block)?)?|Input|View|Field(Cell)?|List|Attachment(Cell)?)?|a(sk|b(le(Header(Cell|View)|Column|View)|View(Item)?))|reeController)|I(n(dex(S(pecifier|et)|Path)|put(Manager|S(tream|erv(iceProvider|er(MouseTracker)?)))|vocation)|gnoreMisspelledWords|mage(Rep|Cell|View)?)|O(ut(putStream|lineView)|pen(GL(Context|Pixel(Buffer|Format)|View)|Panel)|bj(CTypeSerializationCallBack|ect(Controller)?))|D(i(st(antObject(Request)?|ributed(NotificationCenter|Lock))|ctionary|rectoryEnumerator)|ocument(Controller)?|e(serializer|cimalNumber(Behaviors|Handler)?|leteCommand)|at(e(Components|Picker(Cell)?|Formatter)?|a)|ra(wer|ggingInfo))|U(ser(InterfaceValidations|Defaults(Controller)?)|RL(Re(sponse|quest)|Handle(Client)?|C(onnection|ache|redential(Storage)?)|Download(Delegate)?|Prot(ocol(Client)?|ectionSpace)|AuthenticationChallenge(Sender)?)?|n(iqueIDSpecifier|doManager|archiver))|P(ipe|o(sitionalSpecifier|pUpButton(Cell)?|rt(Message|NameServer|Coder)?)|ICTImageRep|ersistentDocument|DFImageRep|a(steboard|nel|ragraphStyle|geLayout)|r(int(Info|er|Operation|Panel)|o(cessInfo|tocolChecker|perty(Specifier|ListSerialization)|gressIndicator|xy)|edicate))|E(numerator|vent|PSImageRep|rror|x(ception|istsCommand|pression))|V(iew(Animation)?|al(idated(ToobarItem|UserInterfaceItem)|ue(Transformer)?))|Keyed(Unarchiver|Archiver)|Qui(ckDrawView|tCommand)|F(ile(Manager|Handle|Wrapper)|o(nt(Manager|Descriptor|Panel)?|rm(Cell|atter)))|W(hoseSpecifier|indow(Controller)?|orkspace)|L(o(c(k(ing)?|ale)|gicalTest)|evelIndicator(Cell)?|ayoutManager)|A(ssertionHandler|nimation|ctionCell|ttributedString|utoreleasePool|TSTypesetter|ppl(ication|e(Script|Event(Manager|Descriptor)))|ffineTransform|lert|r(chiver|ray(Controller)?)))\\\\b\",\n            \"name\": \"support.class.cocoa\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(R(oundingMode|ule(Editor(RowType|NestingMode)|rOrientation)|e(questUserAttentionType|lativePosition))|G(lyphInscription|radientDrawingOptions)|XML(NodeKind|D(ocumentContentKind|TDNodeKind)|ParserError)|M(ultibyteGlyphPacking|apTableOptions)|B(itmapFormat|oxType|ezierPathElement|ackgroundStyle|rowserDropOperation)|S(tr(ing(CompareOptions|DrawingOptions|EncodingConversionOptions)|eam(Status|Event))|p(eechBoundary|litViewDividerStyle)|e(archPathD(irectory|omainMask)|gmentS(tyle|witchTracking))|liderType|aveOptions)|H(TTPCookieAcceptPolicy|ashTableOptions)|N(otification(SuspensionBehavior|Coalescing)|umberFormatter(RoundingMode|Behavior|Style|PadPosition)|etService(sError|Options))|C(haracterCollection|o(lor(RenderingIntent|SpaceModel|PanelMode)|mp(oundPredicateType|arisonPredicateModifier))|ellStateValue|al(culationError|endarUnit))|T(ypesetterControlCharacterAction|imeZoneNameStyle|e(stComparisonOperation|xt(Block(Dimension|V(erticalAlignment|alueType)|Layer)|TableLayoutAlgorithm|FieldBezelStyle))|ableView(SelectionHighlightStyle|ColumnAutoresizingStyle)|rackingAreaOptions)|I(n(sertionPosition|te(rfaceStyle|ger))|mage(RepLoadStatus|Scaling|CacheMode|FrameStyle|LoadStatus|Alignment))|Ope(nGLPixelFormatAttribute|rationQueuePriority)|Date(Picker(Mode|Style)|Formatter(Behavior|Style))|U(RL(RequestCachePolicy|HandleStatus|C(acheStoragePolicy|redentialPersistence))|Integer)|P(o(stingStyle|int(ingDeviceType|erFunctionsOptions)|pUpArrowPosition)|athStyle|r(int(ing(Orientation|PaginationMode)|erTableStatus|PanelOptions)|opertyList(MutabilityOptions|Format)|edicateOperatorType))|ExpressionType|KeyValue(SetMutationKind|Change)|QTMovieLoopMode|F(indPanel(SubstringMatchType|Action)|o(nt(RenderingMode|FamilyClass)|cusRingPlacement))|W(hoseSubelementIdentifier|ind(ingRule|ow(B(utton|ackingLocation)|SharingType|CollectionBehavior)))|L(ine(MovementDirection|SweepDirection|CapStyle|JoinStyle)|evelIndicatorStyle)|Animation(BlockingMode|Curve))\\\\b\",\n            \"name\": \"support.type.cocoa.leopard\"\n        },\n        {\n            \"match\":\n                \"\\\\bC(I(Sampler|Co(ntext|lor)|Image(Accumulator)?|PlugIn(Registration)?|Vector|Kernel|Filter(Generator|Shape)?)|A(Renderer|MediaTiming(Function)?|BasicAnimation|ScrollLayer|Constraint(LayoutManager)?|T(iledLayer|extLayer|rans(ition|action))|OpenGLLayer|PropertyAnimation|KeyframeAnimation|Layer|A(nimation(Group)?|ction)))\\\\b\",\n            \"name\": \"support.class.quartz\"\n        },\n        {\n            \"match\": \"\\\\bC(G(Float|Point|Size|Rect)|IFormat|AConstraintAttribute)\\\\b\",\n            \"name\": \"support.type.quartz\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(R(ect(Edge)?|ange)|G(lyph(Relation|LayoutMode)?|radientType)|M(odalSession|a(trixMode|p(Table|Enumerator)))|B(itmapImageFileType|orderType|uttonType|ezelStyle|ackingStoreType|rowserColumnResizingType)|S(cr(oll(er(Part|Arrow)|ArrowPosition)|eenAuxiliaryOpaque)|tringEncoding|ize|ocketNativeHandle|election(Granularity|Direction|Affinity)|wapped(Double|Float)|aveOperationType)|Ha(sh(Table|Enumerator)|ndler(2)?)|C(o(ntrol(Size|Tint)|mp(ositingOperation|arisonResult))|ell(State|Type|ImagePosition|Attribute))|T(hreadPrivate|ypesetterGlyphInfo|i(ckMarkPosition|tlePosition|meInterval)|o(ol(TipTag|bar(SizeMode|DisplayMode))|kenStyle)|IFFCompression|ext(TabType|Alignment)|ab(State|leViewDropOperation|ViewType)|rackingRectTag)|ImageInterpolation|Zone|OpenGL(ContextAuxiliary|PixelFormatAuxiliary)|D(ocumentChangeType|atePickerElementFlags|ra(werState|gOperation))|UsableScrollerParts|P(oint|r(intingPageOrder|ogressIndicator(Style|Th(ickness|readInfo))))|EventType|KeyValueObservingOptions|Fo(nt(SymbolicTraits|TraitMask|Action)|cusRingType)|W(indow(OrderingMode|Depth)|orkspace(IconCreationOptions|LaunchOptions)|ritingDirection)|L(ineBreakMode|ayout(Status|Direction))|A(nimation(Progress|Effect)|ppl(ication(TerminateReply|DelegateReply|PrintReply)|eEventManagerSuspensionID)|ffineTransformStruct|lertStyle))\\\\b\",\n            \"name\": \"support.type.cocoa\"\n        },\n        {\n            \"match\": \"\\\\bNS(NotFound|Ordered(Ascending|Descending|Same))\\\\b\",\n            \"name\": \"support.constant.cocoa\"\n        },\n        {\n            \"match\": \"\\\\bNS(MenuDidBeginTracking|ViewDidUpdateTrackingAreas)?Notification\\\\b\",\n            \"name\": \"support.constant.notification.cocoa.leopard\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(Menu(Did(RemoveItem|SendAction|ChangeItem|EndTracking|AddItem)|WillSendAction)|S(ystemColorsDidChange|plitView(DidResizeSubviews|WillResizeSubviews))|C(o(nt(extHelpModeDid(Deactivate|Activate)|rolT(intDidChange|extDid(BeginEditing|Change|EndEditing)))|lor(PanelColorDidChange|ListDidChange)|mboBox(Selection(IsChanging|DidChange)|Will(Dismiss|PopUp)))|lassDescriptionNeededForClass)|T(oolbar(DidRemoveItem|WillAddItem)|ext(Storage(DidProcessEditing|WillProcessEditing)|Did(BeginEditing|Change|EndEditing)|View(DidChange(Selection|TypingAttributes)|WillChangeNotifyingTextView))|ableView(Selection(IsChanging|DidChange)|ColumnDid(Resize|Move)))|ImageRepRegistryDidChange|OutlineView(Selection(IsChanging|DidChange)|ColumnDid(Resize|Move)|Item(Did(Collapse|Expand)|Will(Collapse|Expand)))|Drawer(Did(Close|Open)|Will(Close|Open))|PopUpButton(CellWillPopUp|WillPopUp)|View(GlobalFrameDidChange|BoundsDidChange|F(ocusDidChange|rameDidChange))|FontSetChanged|W(indow(Did(Resi(ze|gn(Main|Key))|M(iniaturize|ove)|Become(Main|Key)|ChangeScreen(|Profile)|Deminiaturize|Update|E(ndSheet|xpose))|Will(M(iniaturize|ove)|BeginSheet|Close))|orkspace(SessionDid(ResignActive|BecomeActive)|Did(Mount|TerminateApplication|Unmount|PerformFileOperation|Wake|LaunchApplication)|Will(Sleep|Unmount|PowerOff|LaunchApplication)))|A(ntialiasThresholdChanged|ppl(ication(Did(ResignActive|BecomeActive|Hide|ChangeScreenParameters|U(nhide|pdate)|FinishLaunching)|Will(ResignActive|BecomeActive|Hide|Terminate|U(nhide|pdate)|FinishLaunching))|eEventManagerWillProcessFirstEvent)))Notification\\\\b\",\n            \"name\": \"support.constant.notification.cocoa\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(RuleEditor(RowType(Simple|Compound)|NestingMode(Si(ngle|mple)|Compound|List))|GradientDraws(BeforeStartingLocation|AfterEndingLocation)|M(inusSetExpressionType|a(chPortDeallocate(ReceiveRight|SendRight|None)|pTable(StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality)))|B(oxCustom|undleExecutableArchitecture(X86|I386|PPC(64)?)|etweenPredicateOperatorType|ackgroundStyle(Raised|Dark|L(ight|owered)))|S(tring(DrawingTruncatesLastVisibleLine|EncodingConversion(ExternalRepresentation|AllowLossy))|ubqueryExpressionType|p(e(ech(SentenceBoundary|ImmediateBoundary|WordBoundary)|llingState(GrammarFlag|SpellingFlag))|litViewDividerStyleThi(n|ck))|e(rvice(RequestTimedOutError|M(iscellaneousError|alformedServiceDictionaryError)|InvalidPasteboardDataError|ErrorM(inimum|aximum)|Application(NotFoundError|LaunchFailedError))|gmentStyle(Round(Rect|ed)|SmallSquare|Capsule|Textured(Rounded|Square)|Automatic)))|H(UDWindowMask|ashTable(StrongMemory|CopyIn|ZeroingWeakMemory|ObjectPointerPersonality))|N(oModeColorPanel|etServiceNoAutoRename)|C(hangeRedone|o(ntainsPredicateOperatorType|l(orRenderingIntent(RelativeColorimetric|Saturation|Default|Perceptual|AbsoluteColorimetric)|lectorDisabledOption))|ellHit(None|ContentArea|TrackableArea|EditableTextArea))|T(imeZoneNameStyle(S(hort(Standard|DaylightSaving)|tandard)|DaylightSaving)|extFieldDatePickerStyle|ableViewSelectionHighlightStyle(Regular|SourceList)|racking(Mouse(Moved|EnteredAndExited)|CursorUpdate|InVisibleRect|EnabledDuringMouseDrag|A(ssumeInside|ctive(In(KeyWindow|ActiveApp)|WhenFirstResponder|Always))))|I(n(tersectSetExpressionType|dexedColorSpaceModel)|mageScale(None|Proportionally(Down|UpOrDown)|AxesIndependently))|Ope(nGLPFAAllowOfflineRenderers|rationQueue(DefaultMaxConcurrentOperationCount|Priority(High|Normal|Very(High|Low)|Low)))|D(iacriticInsensitiveSearch|ownloadsDirectory)|U(nionSetExpressionType|TF(16(BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)|32(BigEndianStringEncoding|StringEncoding|LittleEndianStringEncoding)))|P(ointerFunctions(Ma(chVirtualMemory|llocMemory)|Str(ongMemory|uctPersonality)|C(StringPersonality|opyIn)|IntegerPersonality|ZeroingWeakMemory|O(paque(Memory|Personality)|bjectP(ointerPersonality|ersonality)))|at(hStyle(Standard|NavigationBar|PopUp)|ternColorSpaceModel)|rintPanelShows(Scaling|Copies|Orientation|P(a(perSize|ge(Range|SetupAccessory))|review)))|Executable(RuntimeMismatchError|NotLoadableError|ErrorM(inimum|aximum)|L(inkError|oadError)|ArchitectureMismatchError)|KeyValueObservingOption(Initial|Prior)|F(i(ndPanelSubstringMatchType(StartsWith|Contains|EndsWith|FullWord)|leRead(TooLargeError|UnknownStringEncodingError))|orcedOrderingSearch)|Wi(ndow(BackingLocation(MainMemory|Default|VideoMemory)|Sharing(Read(Only|Write)|None)|CollectionBehavior(MoveToActiveSpace|CanJoinAllSpaces|Default))|dthInsensitiveSearch)|AggregateExpressionType)\\\\b\",\n            \"name\": \"support.constant.cocoa.leopard\"\n        },\n        {\n            \"match\":\n                \"\\\\bNS(R(GB(ModeColorPanel|ColorSpaceModel)|ight(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|T(ext(Movement|Alignment)|ab(sBezelBorder|StopType))|ArrowFunctionKey)|ound(RectBezelStyle|Bankers|ed(BezelStyle|TokenStyle|DisclosureBezelStyle)|Down|Up|Plain|Line(CapStyle|JoinStyle))|un(StoppedResponse|ContinuesResponse|AbortedResponse)|e(s(izableWindowMask|et(CursorRectsRunLoopOrdering|FunctionKey))|ce(ssedBezelStyle|iver(sCantHandleCommandScriptError|EvaluationScriptError))|turnTextMovement|doFunctionKey|quiredArgumentsMissingScriptError|l(evancyLevelIndicatorStyle|ative(Before|After))|gular(SquareBezelStyle|ControlSize)|moveTraitFontAction)|a(n(domSubelement|geDateMode)|tingLevelIndicatorStyle|dio(ModeMatrix|Button)))|G(IFFileType|lyph(Below|Inscribe(B(elow|ase)|Over(strike|Below)|Above)|Layout(WithPrevious|A(tAPoint|gainstAPoint))|A(ttribute(BidiLevel|Soft|Inscribe|Elastic)|bove))|r(ooveBorder|eaterThan(Comparison|OrEqualTo(Comparison|PredicateOperatorType)|PredicateOperatorType)|a(y(ModeColorPanel|ColorSpaceModel)|dient(None|Con(cave(Strong|Weak)|vex(Strong|Weak)))|phiteControlTint)))|XML(N(o(tationDeclarationKind|de(CompactEmptyElement|IsCDATA|OptionsNone|Use(SingleQuotes|DoubleQuotes)|Pre(serve(NamespaceOrder|C(haracterReferences|DATA)|DTD|Prefixes|E(ntities|mptyElements)|Quotes|Whitespace|A(ttributeOrder|ll))|ttyPrint)|ExpandEmptyElement))|amespaceKind)|CommentKind|TextKind|InvalidKind|D(ocument(X(MLKind|HTMLKind|Include)|HTMLKind|T(idy(XML|HTML)|extKind)|IncludeContentTypeDeclaration|Validate|Kind)|TDKind)|P(arser(GTRequiredError|XMLDeclNot(StartedError|FinishedError)|Mi(splaced(XMLDeclarationError|CDATAEndStringError)|xedContentDeclNot(StartedError|FinishedError))|S(t(andaloneValueError|ringNot(StartedError|ClosedError))|paceRequiredError|eparatorRequiredError)|N(MTOKENRequiredError|o(t(ationNot(StartedError|FinishedError)|WellBalancedError)|DTDError)|amespaceDeclarationError|AMERequiredError)|C(haracterRef(In(DTDError|PrologError|EpilogError)|AtEOFError)|o(nditionalSectionNot(StartedError|FinishedError)|mment(NotFinishedError|ContainsDoubleHyphenError))|DATANotFinishedError)|TagNameMismatchError|In(ternalError|valid(HexCharacterRefError|C(haracter(RefError|InEntityError|Error)|onditionalSectionError)|DecimalCharacterRefError|URIError|Encoding(NameError|Error)))|OutOfMemoryError|D(ocumentStartError|elegateAbortedParseError|OCTYPEDeclNotFinishedError)|U(RI(RequiredError|FragmentError)|n(declaredEntityError|parsedEntityError|knownEncodingError|finishedTagError))|P(CDATARequiredError|ublicIdentifierRequiredError|arsedEntityRef(MissingSemiError|NoNameError|In(Internal(SubsetError|Error)|PrologError|EpilogError)|AtEOFError)|r(ocessingInstructionNot(StartedError|FinishedError)|ematureDocumentEndError))|E(n(codingNotSupportedError|tity(Ref(In(DTDError|PrologError|EpilogError)|erence(MissingSemiError|WithoutNameError)|LoopError|AtEOFError)|BoundaryError|Not(StartedError|FinishedError)|Is(ParameterError|ExternalError)|ValueRequiredError))|qualExpectedError|lementContentDeclNot(StartedError|FinishedError)|xt(ernalS(tandaloneEntityError|ubsetNotFinishedError)|raContentError)|mptyDocumentError)|L(iteralNot(StartedError|FinishedError)|T(RequiredError|SlashRequiredError)|essThanSymbolInAttributeError)|Attribute(RedefinedError|HasNoValueError|Not(StartedError|FinishedError)|ListNot(StartedError|FinishedError)))|rocessingInstructionKind)|E(ntity(GeneralKind|DeclarationKind|UnparsedKind|P(ar(sedKind|ameterKind)|redefined))|lement(Declaration(MixedKind|UndefinedKind|E(lementKind|mptyKind)|Kind|AnyKind)|Kind))|Attribute(N(MToken(sKind|Kind)|otationKind)|CDATAKind|ID(Ref(sKind|Kind)|Kind)|DeclarationKind|En(tit(yKind|iesKind)|umerationKind)|Kind))|M(i(n(XEdge|iaturizableWindowMask|YEdge|uteCalendarUnit)|terLineJoinStyle|ddleSubelement|xedState)|o(nthCalendarUnit|deSwitchFunctionKey|use(Moved(Mask)?|E(ntered(Mask)?|ventSubtype|xited(Mask)?))|veToBezierPathElement|mentary(ChangeButton|Push(Button|InButton)|Light(Button)?))|enuFunctionKey|a(c(intoshInterfaceStyle|OSRomanStringEncoding)|tchesPredicateOperatorType|ppedRead|x(XEdge|YEdge))|ACHOperatingSystem)|B(MPFileType|o(ttomTabsBezelBorder|ldFontMask|rderlessWindowMask|x(Se(condary|parator)|OldStyle|Primary))|uttLineCapStyle|e(zelBorder|velLineJoinStyle|low(Bottom|Top)|gin(sWith(Comparison|PredicateOperatorType)|FunctionKey))|lueControlTint|ack(spaceCharacter|tabTextMovement|ingStore(Retained|Buffered|Nonretained)|TabCharacter|wardsSearch|groundTab)|r(owser(NoColumnResizing|UserColumnResizing|AutoColumnResizing)|eakFunctionKey))|S(h(ift(JISStringEncoding|KeyMask)|ow(ControlGlyphs|InvisibleGlyphs)|adowlessSquareBezelStyle)|y(s(ReqFunctionKey|tem(D(omainMask|efined(Mask)?)|FunctionKey))|mbolStringEncoding)|c(a(nnedOption|le(None|ToFit|Proportionally))|r(oll(er(NoPart|Increment(Page|Line|Arrow)|Decrement(Page|Line|Arrow)|Knob(Slot)?|Arrows(M(inEnd|axEnd)|None|DefaultSetting))|Wheel(Mask)?|LockFunctionKey)|eenChangedEventType))|t(opFunctionKey|r(ingDrawing(OneShot|DisableScreenFontSubstitution|Uses(DeviceMetrics|FontLeading|LineFragmentOrigin))|eam(Status(Reading|NotOpen|Closed|Open(ing)?|Error|Writing|AtEnd)|Event(Has(BytesAvailable|SpaceAvailable)|None|OpenCompleted|E(ndEncountered|rrorOccurred)))))|i(ngle(DateMode|UnderlineStyle)|ze(DownFontAction|UpFontAction))|olarisOperatingSystem|unOSOperatingSystem|pecialPageOrder|e(condCalendarUnit|lect(By(Character|Paragraph|Word)|i(ng(Next|Previous)|onAffinity(Downstream|Upstream))|edTab|FunctionKey)|gmentSwitchTracking(Momentary|Select(One|Any)))|quareLineCapStyle|witchButton|ave(ToOperation|Op(tions(Yes|No|Ask)|eration)|AsOperation)|mall(SquareBezelStyle|C(ontrolSize|apsFontMask)|IconButtonBezelStyle))|H(ighlightModeMatrix|SBModeColorPanel|o(ur(Minute(SecondDatePickerElementFlag|DatePickerElementFlag)|CalendarUnit)|rizontalRuler|meFunctionKey)|TTPCookieAcceptPolicy(Never|OnlyFromMainDocumentDomain|Always)|e(lp(ButtonBezelStyle|KeyMask|FunctionKey)|avierFontAction)|PUXOperatingSystem)|Year(MonthDa(yDatePickerElementFlag|tePickerElementFlag)|CalendarUnit)|N(o(n(StandardCharacterSetFontMask|ZeroWindingRule|activatingPanelMask|LossyASCIIStringEncoding)|Border|t(ification(SuspensionBehavior(Hold|Coalesce|D(eliverImmediately|rop))|NoCoalescing|CoalescingOn(Sender|Name)|DeliverImmediately|PostToAllSessions)|PredicateType|EqualToPredicateOperatorType)|S(cr(iptError|ollerParts)|ubelement|pecifierError)|CellMask|T(itle|opLevelContainersSpecifierError|abs(BezelBorder|NoBorder|LineBorder))|I(nterfaceStyle|mage)|UnderlineStyle|FontChangeAction)|u(ll(Glyph|CellType)|m(eric(Search|PadKeyMask)|berFormatter(Round(Half(Down|Up|Even)|Ceiling|Down|Up|Floor)|Behavior(10|Default)|S(cientificStyle|pellOutStyle)|NoStyle|CurrencyStyle|DecimalStyle|P(ercentStyle|ad(Before(Suffix|Prefix)|After(Suffix|Prefix))))))|e(t(Services(BadArgumentError|NotFoundError|C(ollisionError|ancelledError)|TimeoutError|InvalidError|UnknownError|ActivityInProgress)|workDomainMask)|wlineCharacter|xt(StepInterfaceStyle|FunctionKey))|EXTSTEPStringEncoding|a(t(iveShortGlyphPacking|uralTextAlignment)|rrowFontMask))|C(hange(ReadOtherContents|GrayCell(Mask)?|BackgroundCell(Mask)?|Cleared|Done|Undone|Autosaved)|MYK(ModeColorPanel|ColorSpaceModel)|ircular(BezelStyle|Slider)|o(n(stantValueExpressionType|t(inuousCapacityLevelIndicatorStyle|entsCellMask|ain(sComparison|erSpecifierError)|rol(Glyph|KeyMask))|densedFontMask)|lor(Panel(RGBModeMask|GrayModeMask|HSBModeMask|C(MYKModeMask|olorListModeMask|ustomPaletteModeMask|rayonModeMask)|WheelModeMask|AllModesMask)|ListModeColorPanel)|reServiceDirectory|m(p(osite(XOR|Source(In|O(ut|ver)|Atop)|Highlight|C(opy|lear)|Destination(In|O(ut|ver)|Atop)|Plus(Darker|Lighter))|ressedFontMask)|mandKeyMask))|u(stom(SelectorPredicateOperatorType|PaletteModeColorPanel)|r(sor(Update(Mask)?|PointingDevice)|veToBezierPathElement))|e(nterT(extAlignment|abStopType)|ll(State|H(ighlighted|as(Image(Horizontal|OnLeftOrBottom)|OverlappingImage))|ChangesContents|Is(Bordered|InsetButton)|Disabled|Editable|LightsBy(Gray|Background|Contents)|AllowsMixedState))|l(ipPagination|o(s(ePathBezierPathElement|ableWindowMask)|ckAndCalendarDatePickerStyle)|ear(ControlTint|DisplayFunctionKey|LineFunctionKey))|a(seInsensitive(Search|PredicateOption)|n(notCreateScriptCommandError|cel(Button|TextMovement))|chesDirectory|lculation(NoError|Overflow|DivideByZero|Underflow|LossOfPrecision)|rriageReturnCharacter)|r(itical(Request|AlertStyle)|ayonModeColorPanel))|T(hick(SquareBezelStyle|erSquareBezelStyle)|ypesetter(Behavior|HorizontalTabAction|ContainerBreakAction|ZeroAdvancementAction|OriginalBehavior|ParagraphBreakAction|WhitespaceAction|L(ineBreakAction|atestBehavior))|i(ckMark(Right|Below|Left|Above)|tledWindowMask|meZoneDatePickerElementFlag)|o(olbarItemVisibilityPriority(Standard|High|User|Low)|pTabsBezelBorder|ggleButton)|IFF(Compression(N(one|EXT)|CCITTFAX(3|4)|OldJPEG|JPEG|PackBits|LZW)|FileType)|e(rminate(Now|Cancel|Later)|xt(Read(InapplicableDocumentTypeError|WriteErrorM(inimum|aximum))|Block(M(i(nimum(Height|Width)|ddleAlignment)|a(rgin|ximum(Height|Width)))|B(o(ttomAlignment|rder)|aselineAlignment)|Height|TopAlignment|P(ercentageValueType|adding)|Width|AbsoluteValueType)|StorageEdited(Characters|Attributes)|CellType|ured(RoundedBezelStyle|BackgroundWindowMask|SquareBezelStyle)|Table(FixedLayoutAlgorithm|AutomaticLayoutAlgorithm)|Field(RoundedBezel|SquareBezel|AndStepperDatePickerStyle)|WriteInapplicableDocumentTypeError|ListPrependEnclosingMarker))|woByteGlyphPacking|ab(Character|TextMovement|le(tP(oint(Mask|EventSubtype)?|roximity(Mask|EventSubtype)?)|Column(NoResizing|UserResizingMask|AutoresizingMask)|View(ReverseSequentialColumnAutoresizingStyle|GridNone|S(olid(HorizontalGridLineMask|VerticalGridLineMask)|equentialColumnAutoresizingStyle)|NoColumnAutoresizing|UniformColumnAutoresizingStyle|FirstColumnOnlyAutoresizingStyle|LastColumnOnlyAutoresizingStyle)))|rackModeMatrix)|I(n(sert(CharFunctionKey|FunctionKey|LineFunctionKey)|t(Type|ernalS(criptError|pecifierError))|dexSubelement|validIndexSpecifierError|formational(Request|AlertStyle)|PredicateOperatorType)|talicFontMask|SO(2022JPStringEncoding|Latin(1StringEncoding|2StringEncoding))|dentityMappingCharacterCollection|llegalTextMovement|mage(R(ight|ep(MatchesDevice|LoadStatus(ReadingHeader|Completed|InvalidData|Un(expectedEOF|knownType)|WillNeedAllData)))|Below|C(ellType|ache(BySize|Never|Default|Always))|Interpolation(High|None|Default|Low)|O(nly|verlaps)|Frame(Gr(oove|ayBezel)|Button|None|Photo)|L(oadStatus(ReadError|C(ompleted|ancelled)|InvalidData|UnexpectedEOF)|eft)|A(lign(Right|Bottom(Right|Left)?|Center|Top(Right|Left)?|Left)|bove)))|O(n(State|eByteGlyphPacking|OffButton|lyScrollerArrows)|ther(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|TextMovement)|SF1OperatingSystem|pe(n(GL(GO(Re(setLibrary|tainRenderers)|ClearFormatCache|FormatCacheSize)|PFA(R(obust|endererID)|M(inimumPolicy|ulti(sample|Screen)|PSafe|aximumPolicy)|BackingStore|S(creenMask|te(ncilSize|reo)|ingleRenderer|upersample|ample(s|Buffers|Alpha))|NoRecovery|C(o(lor(Size|Float)|mpliant)|losestPolicy)|OffScreen|D(oubleBuffer|epthSize)|PixelBuffer|VirtualScreenCount|FullScreen|Window|A(cc(umSize|elerated)|ux(Buffers|DepthStencil)|l(phaSize|lRenderers))))|StepUnicodeReservedBase)|rationNotSupportedForKeyS(criptError|pecifierError))|ffState|KButton|rPredicateType|bjC(B(itfield|oolType)|S(hortType|tr(ingType|uctType)|electorType)|NoType|CharType|ObjectType|DoubleType|UnionType|PointerType|VoidType|FloatType|Long(Type|longType)|ArrayType))|D(i(s(c(losureBezelStyle|reteCapacityLevelIndicatorStyle)|playWindowRunLoopOrdering)|acriticInsensitivePredicateOption|rect(Selection|PredicateModifier))|o(c(ModalWindowMask|ument(Directory|ationDirectory))|ubleType|wn(TextMovement|ArrowFunctionKey))|e(s(cendingPageOrder|ktopDirectory)|cimalTabStopType|v(ice(NColorSpaceModel|IndependentModifierFlagsMask)|eloper(Directory|ApplicationDirectory))|fault(ControlTint|TokenStyle)|lete(Char(acter|FunctionKey)|FunctionKey|LineFunctionKey)|moApplicationDirectory)|a(yCalendarUnit|teFormatter(MediumStyle|Behavior(10|Default)|ShortStyle|NoStyle|FullStyle|LongStyle))|ra(wer(Clos(ingState|edState)|Open(ingState|State))|gOperation(Generic|Move|None|Copy|Delete|Private|Every|Link|All)))|U(ser(CancelledError|D(irectory|omainMask)|FunctionKey)|RL(Handle(NotLoaded|Load(Succeeded|InProgress|Failed))|CredentialPersistence(None|Permanent|ForSession))|n(scaledWindowMask|cachedRead|i(codeStringEncoding|talicFontMask|fiedTitleAndToolbarWindowMask)|d(o(CloseGroupingRunLoopOrdering|FunctionKey)|e(finedDateComponent|rline(Style(Single|None|Thick|Double)|Pattern(Solid|D(ot|ash(Dot(Dot)?)?)))))|known(ColorSpaceModel|P(ointingDevice|ageOrder)|KeyS(criptError|pecifierError))|boldFontMask)|tilityWindowMask|TF8StringEncoding|p(dateWindowsRunLoopOrdering|TextMovement|ArrowFunctionKey))|J(ustifiedTextAlignment|PEG(2000FileType|FileType)|apaneseEUC(GlyphPacking|StringEncoding))|P(o(s(t(Now|erFontMask|WhenIdle|ASAP)|iti(on(Replace|Be(fore|ginning)|End|After)|ve(IntType|DoubleType|FloatType)))|pUp(NoArrow|ArrowAt(Bottom|Center))|werOffEventType|rtraitOrientation)|NGFileType|ush(InCell(Mask)?|OnPushOffButton)|e(n(TipMask|UpperSideMask|PointingDevice|LowerSideMask)|riodic(Mask)?)|P(S(caleField|tatus(Title|Field)|aveButton)|N(ote(Title|Field)|ame(Title|Field))|CopiesField|TitleField|ImageButton|OptionsButton|P(a(perFeedButton|ge(Range(To|From)|ChoiceMatrix))|reviewButton)|LayoutButton)|lainTextTokenStyle|a(useFunctionKey|ragraphSeparatorCharacter|ge(DownFunctionKey|UpFunctionKey))|r(int(ing(ReplyLater|Success|Cancelled|Failure)|ScreenFunctionKey|erTable(NotFound|OK|Error)|FunctionKey)|o(p(ertyList(XMLFormat|MutableContainers(AndLeaves)?|BinaryFormat|Immutable|OpenStepFormat)|rietaryStringEncoding)|gressIndicator(BarStyle|SpinningStyle|Preferred(SmallThickness|Thickness|LargeThickness|AquaThickness)))|e(ssedTab|vFunctionKey))|L(HeightForm|CancelButton|TitleField|ImageButton|O(KButton|rientationMatrix)|UnitsButton|PaperNameButton|WidthForm))|E(n(terCharacter|d(sWith(Comparison|PredicateOperatorType)|FunctionKey))|v(e(nOddWindingRule|rySubelement)|aluatedObjectExpressionType)|qualTo(Comparison|PredicateOperatorType)|ra(serPointingDevice|CalendarUnit|DatePickerElementFlag)|x(clude(10|QuickDrawElementsIconCreationOption)|pandedFontMask|ecuteFunctionKey))|V(i(ew(M(in(XMargin|YMargin)|ax(XMargin|YMargin))|HeightSizable|NotSizable|WidthSizable)|aPanelFontAction)|erticalRuler|a(lidationErrorM(inimum|aximum)|riableExpressionType))|Key(SpecifierEvaluationScriptError|Down(Mask)?|Up(Mask)?|PathExpressionType|Value(MinusSetMutation|SetSetMutation|Change(Re(placement|moval)|Setting|Insertion)|IntersectSetMutation|ObservingOption(New|Old)|UnionSetMutation|ValidationError))|QTMovie(NormalPlayback|Looping(BackAndForthPlayback|Playback))|F(1(1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|7FunctionKey|i(nd(PanelAction(Replace(A(ndFind|ll(InSelection)?))?|S(howFindPanel|e(tFindString|lectAll(InSelection)?))|Next|Previous)|FunctionKey)|tPagination|le(Read(No(SuchFileError|PermissionError)|CorruptFileError|In(validFileNameError|applicableStringEncodingError)|Un(supportedSchemeError|knownError))|HandlingPanel(CancelButton|OKButton)|NoSuchFileError|ErrorM(inimum|aximum)|Write(NoPermissionError|In(validFileNameError|applicableStringEncodingError)|OutOfSpaceError|Un(supportedSchemeError|knownError))|LockingError)|xedPitchFontMask)|2(1FunctionKey|7FunctionKey|2FunctionKey|8FunctionKey|3FunctionKey|9FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey|6FunctionKey)|o(nt(Mo(noSpaceTrait|dernSerifsClass)|BoldTrait|S(ymbolicClass|criptsClass|labSerifsClass|ansSerifClass)|C(o(ndensedTrait|llectionApplicationOnlyMask)|larendonSerifsClass)|TransitionalSerifsClass|I(ntegerAdvancementsRenderingMode|talicTrait)|O(ldStyleSerifsClass|rnamentalsClass)|DefaultRenderingMode|U(nknownClass|IOptimizedTrait)|Panel(S(hadowEffectModeMask|t(andardModesMask|rikethroughEffectModeMask)|izeModeMask)|CollectionModeMask|TextColorEffectModeMask|DocumentColorEffectModeMask|UnderlineEffectModeMask|FaceModeMask|All(ModesMask|EffectsModeMask))|ExpandedTrait|VerticalTrait|F(amilyClassMask|reeformSerifsClass)|Antialiased(RenderingMode|IntegerAdvancementsRenderingMode))|cusRing(Below|Type(None|Default|Exterior)|Only|Above)|urByteGlyphPacking|rm(attingError(M(inimum|aximum))?|FeedCharacter))|8FunctionKey|unction(ExpressionType|KeyMask)|3(1FunctionKey|2FunctionKey|3FunctionKey|4FunctionKey|5FunctionKey|FunctionKey|0FunctionKey)|9FunctionKey|4FunctionKey|P(RevertButton|S(ize(Title|Field)|etButton)|CurrentField|Preview(Button|Field))|l(oat(ingPointSamplesBitmapFormat|Type)|agsChanged(Mask)?)|axButton|5FunctionKey|6FunctionKey)|W(heelModeColorPanel|indow(s(NTOperatingSystem|CP125(1StringEncoding|2StringEncoding|3StringEncoding|4StringEncoding|0StringEncoding)|95(InterfaceStyle|OperatingSystem))|M(iniaturizeButton|ovedEventType)|Below|CloseButton|ToolbarButton|ZoomButton|Out|DocumentIconButton|ExposedEventType|Above)|orkspaceLaunch(NewInstance|InhibitingBackgroundOnly|Default|PreferringClassic|WithoutA(ctivation|ddingToRecents)|A(sync|nd(Hide(Others)?|Print)|llowingClassicStartup))|eek(day(CalendarUnit|OrdinalCalendarUnit)|CalendarUnit)|a(ntsBidiLevels|rningAlertStyle)|r(itingDirection(RightToLeft|Natural|LeftToRight)|apCalendarComponents))|L(i(stModeMatrix|ne(Moves(Right|Down|Up|Left)|B(order|reakBy(C(harWrapping|lipping)|Truncating(Middle|Head|Tail)|WordWrapping))|S(eparatorCharacter|weep(Right|Down|Up|Left))|ToBezierPathElement|DoesntMove|arSlider)|teralSearch|kePredicateOperatorType|ghterFontAction|braryDirectory)|ocalDomainMask|e(ssThan(Comparison|OrEqualTo(Comparison|PredicateOperatorType)|PredicateOperatorType)|ft(Mouse(D(own(Mask)?|ragged(Mask)?)|Up(Mask)?)|T(ext(Movement|Alignment)|ab(sBezelBorder|StopType))|ArrowFunctionKey))|a(yout(RightToLeft|NotDone|CantFit|OutOfGlyphs|Done|LeftToRight)|ndscapeOrientation)|ABColorSpaceModel)|A(sc(iiWithDoubleByteEUCGlyphPacking|endingPageOrder)|n(y(Type|PredicateModifier|EventMask)|choredSearch|imation(Blocking|Nonblocking(Threaded)?|E(ffect(DisappearingItemDefault|Poof)|ase(In(Out)?|Out))|Linear)|dPredicateType)|t(Bottom|tachmentCharacter|omicWrite|Top)|SCIIStringEncoding|d(obe(GB1CharacterCollection|CNS1CharacterCollection|Japan(1CharacterCollection|2CharacterCollection)|Korea1CharacterCollection)|dTraitFontAction|minApplicationDirectory)|uto(saveOperation|Pagination)|pp(lication(SupportDirectory|D(irectory|e(fined(Mask)?|legateReply(Success|Cancel|Failure)|activatedEventType))|ActivatedEventType)|KitDefined(Mask)?)|l(ternateKeyMask|pha(ShiftKeyMask|NonpremultipliedBitmapFormat|FirstBitmapFormat)|ert(SecondButtonReturn|ThirdButtonReturn|OtherReturn|DefaultReturn|ErrorReturn|FirstButtonReturn|AlternateReturn)|l(ScrollerParts|DomainsMask|PredicateModifier|LibrariesDirectory|ApplicationsDirectory))|rgument(sWrongScriptError|EvaluationScriptError)|bove(Bottom|Top)|WTEventType))\\\\b\",\n            \"name\": \"support.constant.cocoa\"\n        },\n        {\n            \"include\": \"source.c\"\n        },\n        {\n            \"include\": \"#bracketed_content\"\n        }\n    ],\n    \"repository\": {\n        \"bracketed_content\": {\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.scope.begin.objc\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.scope.end.objc\"\n                }\n            },\n            \"name\": \"meta.bracketed.objc\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?=predicateWithFormat:)(?<=NSPredicate )(predicateWithFormat:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.any-method.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.arguments.objc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\])\",\n                    \"name\": \"meta.function-call.predicate.objc\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.separator.arguments.objc\"\n                                }\n                            },\n                            \"match\": \"\\\\bargument(Array|s)(:)\",\n                            \"name\": \"support.function.any-method.name-of-parameter.objc\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.separator.arguments.objc\"\n                                }\n                            },\n                            \"match\": \"\\\\b\\\\w+(:)\",\n                            \"name\": \"invalid.illegal.unknown-method.objc\"\n                        },\n                        {\n                            \"begin\": \"@\\\"\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.begin.objc\"\n                                }\n                            },\n                            \"end\": \"\\\"\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.string.end.objc\"\n                                }\n                            },\n                            \"name\": \"string.quoted.double.objc\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\b(AND|OR|NOT|IN)\\\\b\",\n                                    \"name\": \"keyword.operator.logical.predicate.cocoa\"\n                                },\n                                {\n                                    \"match\": \"\\\\b(ALL|ANY|SOME|NONE)\\\\b\",\n                                    \"name\": \"constant.language.predicate.cocoa\"\n                                },\n                                {\n                                    \"match\":\n                                        \"\\\\b(NULL|NIL|SELF|TRUE|YES|FALSE|NO|FIRST|LAST|SIZE)\\\\b\",\n                                    \"name\": \"constant.language.predicate.cocoa\"\n                                },\n                                {\n                                    \"match\": \"\\\\b(MATCHES|CONTAINS|BEGINSWITH|ENDSWITH|BETWEEN)\\\\b\",\n                                    \"name\": \"keyword.operator.comparison.predicate.cocoa\"\n                                },\n                                {\n                                    \"match\": \"\\\\bC(ASEINSENSITIVE|I)\\\\b\",\n                                    \"name\": \"keyword.other.modifier.predicate.cocoa\"\n                                },\n                                {\n                                    \"match\":\n                                        \"\\\\b(ANYKEY|SUBQUERY|CAST|TRUEPREDICATE|FALSEPREDICATE)\\\\b\",\n                                    \"name\": \"keyword.other.predicate.cocoa\"\n                                },\n                                {\n                                    \"match\":\n                                        \"\\\\\\\\(\\\\\\\\|[abefnrtv'\\\"?]|[0-3]\\\\d{,2}|[4-7]\\\\d?|x[a-zA-Z0-9]+)\",\n                                    \"name\": \"constant.character.escape.objc\"\n                                },\n                                {\n                                    \"match\": \"\\\\\\\\.\",\n                                    \"name\": \"invalid.illegal.unknown-escape.objc\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#special_variables\"\n                        },\n                        {\n                            \"include\": \"#c_functions\"\n                        },\n                        {\n                            \"include\": \"$base\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?=\\\\w)(?<=[\\\\w\\\\])\\\"] )(\\\\w+(?:(:)|(?=\\\\])))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.any-method.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.arguments.objc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\])\",\n                    \"name\": \"meta.function-call.objc\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.separator.arguments.objc\"\n                                }\n                            },\n                            \"match\": \"\\\\b\\\\w+(:)\",\n                            \"name\": \"support.function.any-method.name-of-parameter.objc\"\n                        },\n                        {\n                            \"include\": \"#special_variables\"\n                        },\n                        {\n                            \"include\": \"#c_functions\"\n                        },\n                        {\n                            \"include\": \"$base\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#special_variables\"\n                },\n                {\n                    \"include\": \"#c_functions\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"c_functions\": {\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.support.function.leading.c\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.function.C99.c\"\n                        }\n                    },\n                    \"match\":\n                        \"(\\\\s*)\\\\b(hypot(f|l)?|s(scanf|ystem|nprintf|ca(nf|lb(n(f|l)?|ln(f|l)?))|i(n(h(f|l)?|f|l)?|gn(al|bit))|tr(s(tr|pn)|nc(py|at|mp)|c(spn|hr|oll|py|at|mp)|to(imax|d|u(l(l)?|max)|k|f|l(d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(jmp|vbuf|locale|buf)|qrt(f|l)?|w(scanf|printf)|rand)|n(e(arbyint(f|l)?|xt(toward(f|l)?|after(f|l)?))|an(f|l)?)|c(s(in(h(f|l)?|f|l)?|qrt(f|l)?)|cos(h(f)?|f|l)?|imag(f|l)?|t(ime|an(h(f|l)?|f|l)?)|o(s(h(f|l)?|f|l)?|nj(f|l)?|pysign(f|l)?)|p(ow(f|l)?|roj(f|l)?)|e(il(f|l)?|xp(f|l)?)|l(o(ck|g(f|l)?)|earerr)|a(sin(h(f|l)?|f|l)?|cos(h(f|l)?|f|l)?|tan(h(f|l)?|f|l)?|lloc|rg(f|l)?|bs(f|l)?)|real(f|l)?|brt(f|l)?)|t(ime|o(upper|lower)|an(h(f|l)?|f|l)?|runc(f|l)?|gamma(f|l)?|mp(nam|file))|i(s(space|n(ormal|an)|cntrl|inf|digit|u(nordered|pper)|p(unct|rint)|finite|w(space|c(ntrl|type)|digit|upper|p(unct|rint)|lower|al(num|pha)|graph|xdigit|blank)|l(ower|ess(equal|greater)?)|al(num|pha)|gr(eater(equal)?|aph)|xdigit|blank)|logb(f|l)?|max(div|abs))|di(v|fftime)|_Exit|unget(c|wc)|p(ow(f|l)?|ut(s|c(har)?|wc(har)?)|error|rintf)|e(rf(c(f|l)?|f|l)?|x(it|p(2(f|l)?|f|l|m1(f|l)?)?))|v(s(scanf|nprintf|canf|printf|w(scanf|printf))|printf|f(scanf|printf|w(scanf|printf))|w(scanf|printf)|a_(start|copy|end|arg))|qsort|f(s(canf|e(tpos|ek))|close|tell|open|dim(f|l)?|p(classify|ut(s|c|w(s|c))|rintf)|e(holdexcept|set(e(nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(aiseexcept|ror)|get(e(nv|xceptflag)|round))|flush|w(scanf|ide|printf|rite)|loor(f|l)?|abs(f|l)?|get(s|c|pos|w(s|c))|re(open|e|ad|xp(f|l)?)|m(in(f|l)?|od(f|l)?|a(f|l|x(f|l)?)?))|l(d(iv|exp(f|l)?)|o(ngjmp|cal(time|econv)|g(1(p(f|l)?|0(f|l)?)|2(f|l)?|f|l|b(f|l)?)?)|abs|l(div|abs|r(int(f|l)?|ound(f|l)?))|r(int(f|l)?|ound(f|l)?)|gamma(f|l)?)|w(scanf|c(s(s(tr|pn)|nc(py|at|mp)|c(spn|hr|oll|py|at|mp)|to(imax|d|u(l(l)?|max)|k|f|l(d|l)?|mbs)|pbrk|ftime|len|r(chr|tombs)|xfrm)|to(b|mb)|rtomb)|printf|mem(set|c(hr|py|mp)|move))|a(s(sert|ctime|in(h(f|l)?|f|l)?)|cos(h(f|l)?|f|l)?|t(o(i|f|l(l)?)|exit|an(h(f|l)?|2(f|l)?|f|l)?)|b(s|ort))|g(et(s|c(har)?|env|wc(har)?)|mtime)|r(int(f|l)?|ound(f|l)?|e(name|alloc|wind|m(ove|quo(f|l)?|ainder(f|l)?))|a(nd|ise))|b(search|towc)|m(odf(f|l)?|em(set|c(hr|py|mp)|move)|ktime|alloc|b(s(init|towcs|rtowcs)|towc|len|r(towc|len))))\\\\b\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.function-call.leading.c\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.function.any-method.c\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.parameters.c\"\n                        }\n                    },\n                    \"match\":\n                        \"(?x) (?: (?= \\\\s )  (?:(?<=else|new|return) | (?<!\\\\w)) (\\\\s+))?\\n            \\t\\t\\t(\\\\b \\n            \\t\\t\\t\\t(?!(while|for|do|if|else|switch|catch|enumerate|return|r?iterate)\\\\s*\\\\()(?:(?!NS)[A-Za-z_][A-Za-z0-9_]*+\\\\b | :: )++                  # actual name\\n            \\t\\t\\t)\\n            \\t\\t\\t \\\\s*(\\\\()\",\n                    \"name\": \"meta.function-call.c\"\n                }\n            ]\n        },\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"/\\\\*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.objc\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"name\": \"comment.block.objc\"\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?(?=//)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.objc\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"//\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.objc\"\n                                }\n                            },\n                            \"end\": \"\\\\n\",\n                            \"name\": \"comment.line.double-slash.objc\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"(?>\\\\\\\\\\\\s*\\\\n)\",\n                                    \"name\": \"punctuation.separator.continuation.objc\"\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"disabled\": {\n            \"begin\": \"^\\\\s*#\\\\s*if(n?def)?\\\\b.*$\",\n            \"comment\": \"eat nested preprocessor if(def)s\",\n            \"end\": \"^\\\\s*#\\\\s*endif\\\\b.*$\",\n            \"patterns\": [\n                {\n                    \"include\": \"#disabled\"\n                },\n                {\n                    \"include\": \"#pragma-mark\"\n                }\n            ]\n        },\n        \"implementation_innards\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor-rule-enabled-implementation\"\n                },\n                {\n                    \"include\": \"#preprocessor-rule-disabled-implementation\"\n                },\n                {\n                    \"include\": \"#preprocessor-rule-other-implementation\"\n                },\n                {\n                    \"include\": \"#property_directive\"\n                },\n                {\n                    \"include\": \"#special_variables\"\n                },\n                {\n                    \"include\": \"#method_super\"\n                },\n                {\n                    \"include\": \"$base\"\n                }\n            ]\n        },\n        \"interface_innards\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#preprocessor-rule-enabled-interface\"\n                },\n                {\n                    \"include\": \"#preprocessor-rule-disabled-interface\"\n                },\n                {\n                    \"include\": \"#preprocessor-rule-other-interface\"\n                },\n                {\n                    \"include\": \"#properties\"\n                },\n                {\n                    \"include\": \"#protocol_list\"\n                },\n                {\n                    \"include\": \"#method\"\n                },\n                {\n                    \"include\": \"$base\"\n                }\n            ]\n        },\n        \"method\": {\n            \"begin\": \"^(-|\\\\+)\\\\s*\",\n            \"end\": \"(?=\\\\{|#)|;\",\n            \"name\": \"meta.function.objc\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.type.begin.objc\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\\\\s*(\\\\w+\\\\b)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.type.end.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.objc\"\n                        }\n                    },\n                    \"name\": \"meta.return-type.objc\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#protocol_list\"\n                        },\n                        {\n                            \"include\": \"#protocol_type_qualifier\"\n                        },\n                        {\n                            \"include\": \"$base\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"\\\\b\\\\w+(?=:)\",\n                    \"name\": \"entity.name.function.name-of-parameter.objc\"\n                },\n                {\n                    \"begin\": \"((:))\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.name-of-parameter.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.arguments.objc\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.type.begin.objc\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\\\\s*(\\\\w+\\\\b)?\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.type.end.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.parameter.function.objc\"\n                        }\n                    },\n                    \"name\": \"meta.argument-type.objc\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#protocol_list\"\n                        },\n                        {\n                            \"include\": \"#protocol_type_qualifier\"\n                        },\n                        {\n                            \"include\": \"$base\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"method_super\": {\n            \"begin\": \"^(?=-|\\\\+)\",\n            \"end\": \"(?<=\\\\})|(?=#)\",\n            \"name\": \"meta.function-with-body.objc\",\n            \"patterns\": [\n                {\n                    \"include\": \"#method\"\n                },\n                {\n                    \"include\": \"$base\"\n                }\n            ]\n        },\n        \"pragma-mark\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.pragma.c\"\n                },\n                \"3\": {\n                    \"name\": \"meta.toc-list.pragma-mark.c\"\n                }\n            },\n            \"match\": \"^\\\\s*(#\\\\s*(pragma\\\\s+mark)\\\\s+(.*))\",\n            \"name\": \"meta.section\"\n        },\n        \"preprocessor-rule-disabled-implementation\": {\n            \"begin\": \"^\\\\s*(#(if)\\\\s+(0)\\\\b).*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.if.c\"\n                },\n                \"3\": {\n                    \"name\": \"constant.numeric.preprocessor.c\"\n                }\n            },\n            \"end\": \"^\\\\s*(#\\\\s*(endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*(#\\\\s*(else)\\\\b)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"meta.preprocessor.c\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.else.c\"\n                        }\n                    },\n                    \"end\": \"(?=^\\\\s*#\\\\s*endif\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interface_innards\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\",\n                    \"end\": \"(?=^\\\\s*#\\\\s*(else|endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"name\": \"comment.block.preprocessor.if-branch.c\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#disabled\"\n                        },\n                        {\n                            \"include\": \"#pragma-mark\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"preprocessor-rule-disabled-interface\": {\n            \"begin\": \"^\\\\s*(#(if)\\\\s+(0)\\\\b).*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.if.c\"\n                },\n                \"3\": {\n                    \"name\": \"constant.numeric.preprocessor.c\"\n                }\n            },\n            \"end\": \"^\\\\s*(#\\\\s*(endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*(#\\\\s*(else)\\\\b)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"meta.preprocessor.c\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.else.c\"\n                        }\n                    },\n                    \"end\": \"(?=^\\\\s*#\\\\s*endif\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interface_innards\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\",\n                    \"end\": \"(?=^\\\\s*#\\\\s*(else|endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"name\": \"comment.block.preprocessor.if-branch.c\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#disabled\"\n                        },\n                        {\n                            \"include\": \"#pragma-mark\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"preprocessor-rule-enabled-implementation\": {\n            \"begin\": \"^\\\\s*(#(if)\\\\s+(0*1)\\\\b)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.if.c\"\n                },\n                \"3\": {\n                    \"name\": \"constant.numeric.preprocessor.c\"\n                }\n            },\n            \"end\": \"^\\\\s*(#\\\\s*(endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*(#\\\\s*(else)\\\\b).*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"meta.preprocessor.c\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.else.c\"\n                        }\n                    },\n                    \"contentName\": \"comment.block.preprocessor.else-branch.c\",\n                    \"end\": \"(?=^\\\\s*#\\\\s*endif\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#disabled\"\n                        },\n                        {\n                            \"include\": \"#pragma-mark\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\",\n                    \"end\": \"(?=^\\\\s*#\\\\s*(else|endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#implementation_innards\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"preprocessor-rule-enabled-interface\": {\n            \"begin\": \"^\\\\s*(#(if)\\\\s+(0*1)\\\\b)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.if.c\"\n                },\n                \"3\": {\n                    \"name\": \"constant.numeric.preprocessor.c\"\n                }\n            },\n            \"end\": \"^\\\\s*(#\\\\s*(endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*(#\\\\s*(else)\\\\b).*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"meta.preprocessor.c\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.else.c\"\n                        }\n                    },\n                    \"contentName\": \"comment.block.preprocessor.else-branch.c\",\n                    \"end\": \"(?=^\\\\s*#\\\\s*endif\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#disabled\"\n                        },\n                        {\n                            \"include\": \"#pragma-mark\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\",\n                    \"end\": \"(?=^\\\\s*#\\\\s*(else|endif)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interface_innards\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"preprocessor-rule-other-implementation\": {\n            \"begin\": \"^\\\\s*(#\\\\s*(if(n?def)?)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.c\"\n                }\n            },\n            \"end\": \"^\\\\s*(#\\\\s*(endif)\\\\b).*?(?:(?=(?://|/\\\\*))|$)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#implementation_innards\"\n                }\n            ]\n        },\n        \"preprocessor-rule-other-interface\": {\n            \"begin\": \"^\\\\s*(#\\\\s*(if(n?def)?)\\\\b.*?(?:(?=(?://|/\\\\*))|$))\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"meta.preprocessor.c\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.c\"\n                }\n            },\n            \"end\": \"^\\\\s*(#\\\\s*(endif)\\\\b).*?(?:(?=(?://|/\\\\*))|$)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interface_innards\"\n                }\n            ]\n        },\n        \"properties\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"((@)property)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.property.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.objc\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.section.scope.begin.objc\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.scope.end.objc\"\n                        }\n                    },\n                    \"name\": \"meta.property-with-attributes.objc\",\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"\\\\b(getter|setter|readonly|readwrite|assign|retain|copy|nonatomic|strong|weak)\\\\b\",\n                            \"name\": \"keyword.other.property.attribute\"\n                        }\n                    ]\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.property.objc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.objc\"\n                        }\n                    },\n                    \"match\": \"((@)property)\\\\b\",\n                    \"name\": \"meta.property.objc\"\n                }\n            ]\n        },\n        \"property_directive\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.objc\"\n                }\n            },\n            \"match\": \"(@)(dynamic|synthesize)\\\\b\",\n            \"name\": \"keyword.other.property.directive.objc\"\n        },\n        \"protocol_list\": {\n            \"begin\": \"(<)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.scope.begin.objc\"\n                }\n            },\n            \"end\": \"(>)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.scope.end.objc\"\n                }\n            },\n            \"name\": \"meta.protocol-list.objc\",\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"\\\\bNS(GlyphStorage|M(utableCopying|enuItem)|C(hangeSpelling|o(ding|pying|lorPicking(Custom|Default)))|T(oolbarItemValidations|ext(Input|AttachmentCell))|I(nputServ(iceProvider|erMouseTracker)|gnoreMisspelledWords)|Obj(CTypeSerializationCallBack|ect)|D(ecimalNumberBehaviors|raggingInfo)|U(serInterfaceValidations|RL(HandleClient|DownloadDelegate|ProtocolClient|AuthenticationChallengeSender))|Validated(ToobarItem|UserInterfaceItem)|Locking)\\\\b\",\n                    \"name\": \"support.other.protocol.objc\"\n                }\n            ]\n        },\n        \"protocol_type_qualifier\": {\n            \"match\": \"\\\\b(in|out|inout|oneway|bycopy|byref)\\\\b\",\n            \"name\": \"storage.modifier.protocol.objc\"\n        },\n        \"special_variables\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b_cmd\\\\b\",\n                    \"name\": \"variable.other.selector.objc\"\n                },\n                {\n                    \"match\": \"\\\\b(self|super)\\\\b\",\n                    \"name\": \"variable.language.objc\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/oni-plugin-markdown-preview/package.json",
    "content": "{\n    \"name\": \"oni-plugin-markdown-preview\",\n    \"version\": \"0.0.1\",\n    \"main\": \"lib/index.js\",\n    \"engines\": {\n        \"oni\": \"^0.0.1\"\n    },\n    \"scripts\": {\n        \"build\": \"rimraf lib && tsc\",\n        \"test\": \"tsc -p tsconfig.test.json && mocha --recursive ./lib_test/test\"\n    },\n    \"oni\": {\n        \"supportedFileTypes\": [\n            \"markdown\"\n        ],\n        \"commands\": {\n            \"markdown.preview\": {\n                \"name\": \"Markdown Preview\",\n                \"details\": \"Preview open markdown file\"\n            }\n        }\n    },\n    \"tbd-dependencies\": {\n        \"marked\": \"^0.4.0\",\n        \"dompurify\": \"1.0.2\",\n        \"highlight.js\": \"^9.12.0\",\n        \"oni-types\": \"^0.0.4\",\n        \"oni-api\": \"^0.0.9\"\n    },\n    \"tbd-peerDependencies\": {\n        \"typescript\": \"^2.5.3\",\n        \"rimraf\": \"^2.6.2\"\n    },\n    \"tbd-devDependencies\": {\n        \"@types/highlight.js\": \"^9.12.2\",\n        \"typescript\": \"2.5.3\",\n        \"rimraf\": \"2.6.2\"\n    }\n}\n"
  },
  {
    "path": "extensions/oni-plugin-markdown-preview/src/index.tsx",
    "content": "import { EventCallback, IDisposable, IEvent } from \"oni-types\"\n\nimport * as dompurify from \"dompurify\"\nimport * as hljs from \"highlight.js\"\nimport * as marked from \"marked\"\nimport * as Oni from \"oni-api\"\nimport * as React from \"react\"\n\n/**\n * Props are like the constructor arguments\n * for the React component (immutable)\n */\ninterface IMarkdownPreviewProps {\n    oni: Oni.Plugin.Api\n    instance: MarkdownPreviewEditor\n}\n\ninterface IColors {\n    background: string\n    foreground: string\n    link: string\n    codeBackground: string\n    codeForeground: string\n    codeBorder: string\n}\n\ninterface IMarkdownPreviewState {\n    source: string\n    colors: IColors\n}\n\nconst generateScrollingAnchorId = (line: number) => {\n    return \"scrolling-anchor-id-\" + line\n}\n\nclass MarkdownPreview extends React.PureComponent<IMarkdownPreviewProps, IMarkdownPreviewState> {\n    private _subscriptions: IDisposable[] = []\n\n    constructor(props: IMarkdownPreviewProps) {\n        super(props)\n\n        const colors: IColors = {\n            background: this.props.oni.colors.getColor(\"editor.background\"),\n            foreground: this.props.oni.colors.getColor(\"editor.foreground\"),\n            link: this.props.oni.colors.getColor(\"highlight.mode.normal.background\"),\n            codeBackground: this.props.oni.colors.getColor(\"background\"),\n            codeForeground: this.props.oni.colors.getColor(\"foreground\"),\n            codeBorder: this.props.oni.colors.getColor(\"toolTip.border\"),\n        }\n\n        this.state = { source: \"\", colors }\n    }\n\n    public componentDidMount() {\n        const activeEditor: Oni.Editor = this.props.oni.editors.activeEditor\n\n        if (!activeEditor) {\n            return\n        }\n\n        this.subscribe(activeEditor.onBufferChanged, args => this.onBufferChanged(args))\n        // TODO: Subscribe \"onFocusChanged\"\n\n        if (this.props.oni.configuration.getValue(\"experimental.markdownPreview.autoScroll\")) {\n            this.subscribe(activeEditor.onBufferScrolled, args => this.onBufferScrolled(args))\n        }\n\n        this.previewBuffer(activeEditor.activeBuffer)\n    }\n\n    public componentWillUnmount() {\n        for (const subscription of this._subscriptions) {\n            subscription.dispose()\n        }\n        this._subscriptions = []\n    }\n\n    public render(): JSX.Element {\n        const renderedMarkdown = this.generateMarkdown()\n        this.props.instance.updateContent(this.state.source, renderedMarkdown)\n        const html = renderedMarkdown + this.generateContainerStyle()\n        const classes = \"stack enable-mouse oniPluginMarkdownPreviewContainerStyle\"\n        return <div className={classes} dangerouslySetInnerHTML={{ __html: html }} />\n    }\n\n    private generateContainerStyle(): string {\n        const colors = this.state.colors\n        const syntaxHighlightTheme = this.props.oni.configuration.getValue(\n            \"experimental.markdownPreview.syntaxTheme\",\n        )\n\n        const codeBlockStyle = `\n            background: ${colors.codeBackground};\n            color: ${colors.codeForeground};\n            border-color: ${colors.codeBackground};\n            font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif\n            padding: 0.4em 0.4em 0.4em 0.4em;\n            margin: 0.4em 0.4em 0.4em 0.4em;\n        `\n\n        return `\n            <link rel=\"stylesheet\" href=\"node_modules/highlight.js/styles/${syntaxHighlightTheme}.css\">\n\n            <style>\n            .oniPluginMarkdownPreviewContainerStyle {\n                padding: 1em 1em 1em 1em;\n                overflow-y: auto;\n                background: ${colors.background};\n                color: ${colors.foreground};\n            }\n\n            .oniPluginMarkdownPreviewContainerStyle a:link {\n                color: ${colors.link};\n            }\n\n            .oniPluginMarkdownPreviewContainerStyle pre {\n                display: flex;\n                ${codeBlockStyle}\n            }\n\n            .oniPluginMarkdownPreviewContainerStyle code {\n                ${codeBlockStyle}\n            }\n            </style>\n        `\n    }\n\n    private generateMarkdown(): string {\n        const markdownLines: string[] = dompurify.sanitize(this.state.source).split(\"\\n\")\n\n        const generateAnchor = (line: number): string => {\n            return `<a id=\"${generateScrollingAnchorId(line)}\"></a>`\n        }\n\n        let isBlock: boolean = false\n        const originalLinesCount: number = markdownLines.length - 1\n        // tslint:disable-next-line\n        for (var i = originalLinesCount; i > 0; i--) {\n            if (markdownLines[i].includes(\"```\")) {\n                isBlock = !isBlock\n            } else if (isBlock) {\n                // Skip blocks\n            } else if (markdownLines[i].trim() === \"\") {\n                // Skip empty lines\n            } else {\n                markdownLines.splice(i, 0, generateAnchor(i))\n            }\n        }\n        markdownLines.splice(0, 0, generateAnchor(i))\n        markdownLines.push(generateAnchor(originalLinesCount - 1))\n\n        const markedOptions = {\n            baseUrl: this.props.oni.workspace.activeWorkspace,\n            highlight(code, lang) {\n                return code\n            },\n        }\n\n        const highlightsEnabled = this.props.oni.configuration.getValue(\n            \"experimental.markdownPreview.syntaxHighlights\",\n        )\n\n        if (highlightsEnabled) {\n            markedOptions.highlight = (code, lang) => {\n                const languageExists = hljs.getLanguage(lang)\n                const languageNotDefinedOrInvalid =\n                    typeof lang === \"undefined\" ||\n                    (typeof languageExists === \"undefined\" && lang !== \"nohighlight\")\n\n                if (languageNotDefinedOrInvalid) {\n                    return hljs.highlightAuto(code).value\n                }\n\n                if (lang === \"nohighlight\") {\n                    return code\n                }\n\n                return hljs.highlight(lang, code).value\n            }\n        }\n\n        marked.setOptions(markedOptions)\n\n        return marked(markdownLines.join(\"\\n\"))\n    }\n\n    private subscribe<T>(editorEvent: IEvent<T>, eventCallback: EventCallback<T>): void {\n        this._subscriptions.push(editorEvent.subscribe(eventCallback))\n    }\n\n    private onBufferChanged(bufferInfo: Oni.EditorBufferChangedEventArgs): void {\n        if (bufferInfo.buffer.language === \"markdown\") {\n            this.previewBuffer(bufferInfo.buffer)\n        }\n    }\n\n    private onBufferScrolled(args: Oni.EditorBufferScrolledEventArgs): void {\n        if (this.props.oni.editors.activeEditor.activeBuffer.language !== \"markdown\") {\n            return\n        }\n\n        let anchor = null\n        for (let line = args.windowTopLine - 1; !anchor && line < args.bufferTotalLines; line++) {\n            anchor = document.getElementById(generateScrollingAnchorId(line))\n        }\n\n        if (anchor) {\n            anchor.scrollIntoView()\n        }\n    }\n\n    private previewBuffer(buffer: Oni.Buffer): void {\n        buffer.getLines().then((lines: string[]) => {\n            this.previewString(lines.join(\"\\n\"))\n        })\n    }\n\n    private previewString(str: string): void {\n        this.setState({ source: str })\n    }\n}\n\nclass MarkdownPreviewEditor implements Oni.IWindowSplit {\n    private _open: boolean = false\n    private _manuallyClosed: boolean = false\n    private _unrenderedContent: string = \"\"\n    private _renderedContent: string = \"\"\n    private _split: Oni.WindowSplitHandle\n\n    constructor(private _oni: Oni.Plugin.Api) {\n        this._oni.editors.activeEditor.onBufferEnter.subscribe(args => this.onBufferEnter(args))\n        this._oni.editors.activeEditor.onBufferLeave.subscribe(args => this.onBufferLeave(args))\n    }\n\n    public isPaneOpen(): boolean {\n        return this._open\n    }\n\n    public getUnrenderedContent(): string {\n        return this._unrenderedContent\n    }\n\n    public getRenderedContent(): string {\n        return this._renderedContent\n    }\n\n    public updateContent(unrendered: string, rendered: string): void {\n        this._unrenderedContent = unrendered\n        this._renderedContent = rendered\n    }\n\n    public toggle(): void {\n        if (this._open) {\n            this.close(true)\n        } else {\n            this.open()\n        }\n    }\n\n    public open(): void {\n        if (!this._open) {\n            this._open = true\n            this._manuallyClosed = false\n            const editorSplit = this._oni.windows.activeSplitHandle\n\n            // TODO: Update API\n            this._split = this._oni.windows.createSplit(\"vertical\", this)\n            editorSplit.focus()\n        }\n    }\n\n    public close(manuallyClosed = false): void {\n        if (this._open) {\n            this._open = false\n            this._manuallyClosed = manuallyClosed\n            this._split.close()\n        }\n    }\n\n    public render(): JSX.Element {\n        return <MarkdownPreview oni={this._oni} instance={this} />\n    }\n\n    private onBufferEnter(bufferInfo: Oni.EditorBufferEventArgs): void {\n        if (bufferInfo.language === \"markdown\" && this._manuallyClosed === false) {\n            this.open()\n        }\n    }\n\n    private onBufferLeave(bufferInfo: Oni.EditorBufferEventArgs): void {\n        this.close()\n    }\n}\n\nexport function activate(oni: any): any {\n    if (!oni.configuration.getValue(\"experimental.markdownPreview.enabled\", false)) {\n        return\n    }\n\n    const preview = new MarkdownPreviewEditor(oni)\n\n    oni.commands.registerCommand(\n        new Command(\n            \"markdown.openPreview\",\n            \"Open Markdown Preview\",\n            \"Open the Markdown preview pane if it is not already opened\",\n            () => {\n                preview.open()\n            },\n        ),\n    )\n\n    oni.commands.registerCommand(\n        new Command(\n            \"markdown.closePreview\",\n            \"Close Markdown Preview\",\n            \"Close the Markdown preview pane if it is not already closed\",\n            () => {\n                preview.close(true)\n            },\n        ),\n    )\n\n    oni.commands.registerCommand(\n        new Command(\n            \"markdown.togglePreview\",\n            \"Toggle Markdown Preview\",\n            \"Open the Markdown preview pane if it is closed, otherwise open it\",\n            () => {\n                preview.toggle()\n            },\n        ),\n    )\n\n    return preview as any\n}\n\nclass Command implements Oni.Commands.ICommand {\n    constructor(\n        public command: string,\n        public name: string,\n        public detail: string,\n        public execute: Oni.Commands.CommandCallback,\n    ) {}\n}\n"
  },
  {
    "path": "extensions/oni-plugin-markdown-preview/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"preserveConstEnums\": true,\n        \"outDir\": \"./lib\",\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"declaration\": true,\n        \"sourceMap\": true,\n        \"target\": \"es2015\",\n        \"skipLibCheck\": true\n    },\n    \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "extensions/oni-plugin-prettier/.eslintrc.json",
    "content": "{\n    \"rules\": {\n        \"indent\": 0,\n        \"linebreak-style\": [\"off\", \"unix\"],\n        \"quotes\": [\"error\", \"double\", { \"allowTemplateLiterals\": true }],\n        \"semi\": [\"error\", \"never\"],\n        \"array-callback-return\": \"error\",\n        \"eqeqeq\": \"error\",\n        \"no-console\": \"on\",\n        \"strict\": 0,\n        \"no-unused-vars\": 0,\n        \"no-undef\": 1,\n        \"no-undefined\": 1,\n        \"camelcase\": 1,\n        \"no-underscore-dangle\": 0,\n        \"no-console\": 0,\n        \"no-invalid-this\": 1,\n        \"no-useless-return\": 1,\n        \"comma-dangle\": [\"error\", \"only-multiline\"],\n        \"comma-spacing\": [\"error\", { \"before\": false, \"after\": true }]\n    },\n    \"env\": {\n        \"es6\": true,\n        \"browser\": true,\n        \"jasmine\": true,\n        \"mocha\": true\n    },\n    \"settings\": {\n        \"ecmascript\": 6,\n        \"jsx\": true\n    },\n    \"extends\": \"eslint:recommended\",\n    \"parser\": \"babel-eslint\",\n    \"plugins\": [\"react\"],\n    \"globals\": {\n        \"_\": false,\n        \"remote\": false,\n        \"process\": false,\n        \"module\": false,\n        \"require\": false,\n        \"__dirname\": false,\n        \"preloadedData\": false\n    },\n    \"root\": true\n}\n"
  },
  {
    "path": "extensions/oni-plugin-prettier/index.js",
    "content": "const path = require(\"path\")\nconst { requireLocalPkg } = require(\"./requirePackage\")\n\n// Helper functions\nconst compose = (...fns) => argument => fns.reduceRight((arg, fn) => fn(arg), argument)\nconst joinOrSplit = (method, by = \"\\n\") => array => array[method](by)\nconst join = joinOrSplit(\"join\")\nconst split = joinOrSplit(\"split\")\nconst isEqual = toCompare => initialItem => initialItem === toCompare\nconst isTrue = (...args) => args.every(a => Boolean(a))\nconst eitherOr = (...args) => args.find(a => !!a)\nconst flatten = multidimensional => [].concat(...multidimensional)\n\nconst isCompatible = (allowedFiletypes, defaultFiletypes) => filePath => {\n    const filetypes = isTrue(allowedFiletypes, Array.isArray(allowedFiletypes))\n        ? allowedFiletypes\n        : defaultFiletypes\n    const extension = path.extname(filePath)\n    return filetypes.includes(extension)\n}\n\nconst getSupportedLanguages = async prettier => {\n    const info = await prettier.getSupportInfo()\n    return flatten(info.languages.map(lang => lang.extensions))\n}\n\nconst activate = async Oni => {\n    // Prettier Module to Use - local or oni-bundled\n    let PrettierModule = requireLocalPkg(process.cwd(), \"prettier\")\n\n    const config = Oni.configuration.getValue(\"oni.plugins.prettier\")\n    const prettierItem = Oni.statusBar.createItem(0, \"oni.plugins.prettier\")\n\n    // Update Prettier Module to use when oni dir changes\n    Oni.workspace.onDirectoryChanged.subscribe(dir => {\n        PrettierModule = requireLocalPkg(dir, \"prettier\")\n    })\n\n    const applyPrettierWithState = applyPrettier()\n    const defaultFiletypes = await getSupportedLanguages(PrettierModule)\n\n    const callback = async () => {\n        const isNormalMode = Oni.editors.activeEditor.mode === \"normal\"\n        if (isNormalMode) {\n            await applyPrettierWithState(Oni)\n        }\n    }\n    Oni.commands.registerCommand({\n        command: \"autoformat.prettier\",\n        name: \"Autoformat with Prettier\",\n        execute: callback,\n    })\n\n    const checkPrettierrc = async bufferPath => {\n        if (!bufferPath) {\n            throw new Error(`No buffer path passed for prettier to check for a Prettierrc`)\n        }\n        try {\n            return await PrettierModule.resolveConfig(bufferPath)\n        } catch (e) {\n            throw new Error(`Error parsing config file, ${e}`)\n        }\n    }\n\n    // Status Bar Component ----\n    const { errorElement, successElement, prettierElement } = createPrettierComponent(Oni, callback)\n\n    prettierItem.setContents(prettierElement)\n\n    const setStatusBarContents = (statusBarItem, defaultElement) => async (\n        statusElement,\n        timeOut = 3500,\n    ) => {\n        statusBarItem.setContents(statusElement)\n        await setTimeout(() => statusBarItem.setContents(defaultElement), timeOut)\n    }\n\n    const setPrettierStatus = setStatusBarContents(prettierItem, prettierElement)\n\n    function applyPrettier() {\n        // Track the buffer state within the function using a closure\n        // if the buffer as a string is the same as the last state\n        // do no format because nothing has changed\n        let lastBufferState = null\n\n        // pass in Oni explicitly - Make dependencies clearer\n        return async Oni => {\n            const { activeBuffer } = Oni.editors.activeEditor\n\n            const [arrayOfLines, { line, character }] = await Promise.all([\n                activeBuffer.getLines(),\n                activeBuffer.getCursorPosition(),\n            ])\n\n            const hasNotChanged = compose(isEqual(lastBufferState), join)\n\n            if (hasNotChanged(arrayOfLines)) {\n                return\n            }\n\n            try {\n                const prettierrc = await checkPrettierrc(activeBuffer.filePath)\n                const prettierConfig = eitherOr(prettierrc, config.settings)\n\n                // Pass in the file path so prettier can infer the correct parser to use\n                const { formatted, cursorOffset } = PrettierModule.formatWithCursor(\n                    join(arrayOfLines),\n                    Object.assign({ filepath: activeBuffer.filePath }, prettierConfig, {\n                        cursorOffset: activeBuffer.cursorOffset,\n                    }),\n                )\n                if (!formatted) {\n                    throw new Error(\"Couldn't format the buffer\")\n                }\n\n                await setPrettierStatus(successElement)\n\n                const withoutFinalCR = formatted.replace(/\\n$/, \"\")\n                lastBufferState = withoutFinalCR\n\n                const [, { character, line }] = await Promise.all([\n                    activeBuffer.setLines(0, arrayOfLines.length, split(withoutFinalCR)),\n                    activeBuffer.convertOffsetToLineColumn(cursorOffset),\n                ])\n\n                await activeBuffer.setCursorPosition(line, character)\n                await Oni.editors.activeEditor.neovim.command(\"w\")\n            } catch (e) {\n                console.warn(`Couldn't format the buffer because: ${e}`)\n                await setPrettierStatus(errorElement)\n            }\n        }\n    }\n\n    const { allowedFiletypes, formatOnSave, enabled } = config\n    const checkCompatibility = isCompatible(allowedFiletypes, defaultFiletypes)\n\n    Oni.editors.activeEditor.onBufferEnter.subscribe(({ filePath }) => {\n        const hasCompatibility = checkCompatibility(filePath)\n\n        hasCompatibility ? prettierItem.show() : prettierItem.hide()\n    })\n\n    Oni.editors.activeEditor.onBufferSaved.subscribe(async ({ filePath }) => {\n        const hasCompatibility = checkCompatibility(filePath)\n\n        const canApplyPrettier = isTrue(formatOnSave, enabled, hasCompatibility)\n        if (canApplyPrettier) {\n            await applyPrettierWithState(Oni)\n        }\n    })\n    return { applyPrettier: applyPrettierWithState, checkCompatibility, checkPrettierrc }\n}\n\nfunction createPrettierComponent(Oni, onClick) {\n    const { React } = Oni.dependencies\n\n    const background = Oni.colors.getColor(\"highlight.mode.normal.background\")\n    const foreground = Oni.colors.getColor(\"highlight.mode.normal.foreground\")\n    const style = {\n        width: \"100%\",\n        height: \"100%\",\n        display: \"flex\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        paddingLeft: \"8px\",\n        paddingRight: \"8px\",\n        color: \"white\",\n    }\n\n    const prettierIcon = (type = \"magic\") =>\n        Oni.ui.createIcon({\n            name: type,\n            size: Oni.ui.iconSize.Default,\n        })\n\n    const iconContainer = (type, color = \"white\") =>\n        React.createElement(\"div\", { style: { padding: \"0 6px 0 0\", color } }, prettierIcon(type))\n\n    const prettierElement = React.createElement(\n        \"div\",\n        { className: \"prettier\", style, onClick },\n        iconContainer(),\n        \"prettier\",\n    )\n\n    const errorElement = React.createElement(\n        \"div\",\n        { style, className: \"prettier\" },\n        iconContainer(\"exclamation-triangle\", \"yellow\"),\n        \"prettier\",\n    )\n\n    const successElement = React.createElement(\n        \"div\",\n        { style, className: \"prettier\" },\n        iconContainer(\"check\", \"#5AB379\"),\n        \"prettier\",\n    )\n\n    return {\n        errorElement,\n        prettierElement,\n        successElement,\n    }\n}\n\nmodule.exports = { activate }\n"
  },
  {
    "path": "extensions/oni-plugin-prettier/package.json",
    "content": "{\n    \"name\": \"oni-plugin-prettier\",\n    \"version\": \"1.0.0\",\n    \"main\": \"index.js\",\n    \"engines\": {\n        \"oni\": \"^0.2.6\"\n    },\n    \"scripts\": {},\n    \"oni\": {\n        \"supportedFileTypes\": [\n            \"*\"\n        ]\n    },\n    \"dependencies\": {\n        \"prettier\": \"^1.13.6\",\n        \"read-pkg-up\": \"^4.0.0\",\n        \"resolve\": \"^1.8.1\"\n    },\n    \"devDependencies\": {}\n}\n"
  },
  {
    "path": "extensions/oni-plugin-prettier/requirePackage.js",
    "content": "const path = require(\"path\")\nconst resolve = require(\"resolve\")\nconst readPkgUp = require(\"read-pkg-up\")\n\n// CREDIT: Shamelessly *borrowed* from prettier-vscode\n\n/**\n * Recursively search for a package.json upwards containing given package\n * as a dependency or devDependency.\n * @param {string} fspath file system path to start searching from\n * @param {string} pkgName package's name to search for\n * @returns {string} resolved path to prettier\n */\nfunction findPkg(fspath = process.cwd(), pkgName) {\n    const res = readPkgUp.sync({ cwd: fspath, normalize: false })\n    const { root } = path.parse(fspath)\n    if (\n        res.pkg &&\n        ((res.pkg.dependencies && res.pkg.dependencies[pkgName]) ||\n            (res.pkg.devDependencies && res.pkg.devDependencies[pkgName]))\n    ) {\n        return resolve.sync(pkgName, { basedir: res.path })\n    } else if (res.path) {\n        const parent = path.resolve(path.dirname(res.path), \"..\")\n        if (parent !== root) {\n            return findPkg(parent, pkgName)\n        }\n    }\n    return\n}\n\n/**\n * Require package explicitely installed relative to given path.\n * Fallback to bundled one if no pacakge was found bottom up.\n * @param {string} fspath file system path starting point to resolve package\n * @param {string} pkgName package's name to require\n * @returns module\n */\nfunction requireLocalPkg(fspath, pkgName) {\n    const modulePath = findPkg(fspath, pkgName)\n    if (modulePath) {\n        try {\n            return require(modulePath)\n        } catch (e) {\n            console.warn(`Failed to load ${pkgName} from ${modulePath}. Using bundled`)\n        }\n    }\n\n    return require(pkgName)\n}\n\nmodule.exports = { requireLocalPkg }\n"
  },
  {
    "path": "extensions/oni-plugin-quickopen/package.json",
    "content": "{\n    \"name\": \"oni-plugin-quickopen\",\n    \"version\": \"0.0.1\",\n    \"main\": \"lib/index.js\",\n    \"engines\": {\n        \"oni\": \"^0.0.1\"\n    },\n    \"scripts\": {\n        \"build\": \"rimraf lib && tsc\",\n        \"test\": \"tsc -p tsconfig.test.json && mocha --recursive ./lib_test/test\"\n    },\n    \"oni\": {\n    },\n    \"dependencies\": {\n        \"oni-types\": \"^0.0.4\",\n        \"oni-api\": \"^0.0.9\"\n    },\n    \"devDependencies\": {\n        \"typescript\": \"2.5.3\",\n        \"rimraf\": \"2.6.2\"\n    }\n}\n"
  },
  {
    "path": "extensions/oni-plugin-quickopen/src/BookmarksSearch.ts",
    "content": "import { Plugin, Menu, Buffer } from \"oni-api\"\nimport { readdir, stat, pathExists } from \"fs-extra\"\nimport { homedir } from \"os\"\nimport { Event, IEvent } from \"oni-types\"\nimport * as path from \"path\"\n\nimport { IAsyncSearch, QuickOpenResult } from \"./QuickOpen\"\nimport { QuickOpenItem, QuickOpenType } from \"./QuickOpenItem\"\n\nexport interface IBookmarkItem {\n    fullPath: string\n    type: string\n}\n\nexport default class BookmarkSearch implements IAsyncSearch {\n    private _onSearchResults = new Event<QuickOpenResult>()\n    private _bookmarkItems: QuickOpenItem[]\n\n    constructor(private _oni: Plugin.Api) {\n        const bookmarks = this._oni.configuration.getValue<string[]>(\"oni.bookmarks\", [])\n\n        // TODO: Consider adding folders as well (recursive async with ignores/excludes)\n        this._bookmarkItems = [\n            new QuickOpenItem(\"Open Folder\", \"\", QuickOpenType.folderHelp),\n            ...bookmarks.map(\n                folder => new QuickOpenItem(folder, \"\", QuickOpenType.bookmark, folder),\n            ),\n            new QuickOpenItem(\n                \"Open configuration\",\n                \"For adding a bookmark\",\n                QuickOpenType.bookmarkHelp,\n            ),\n        ]\n    }\n\n    private _getBookmarkPath = (bookmark: string) => {\n        if (path.isAbsolute(bookmark)) {\n            return bookmark\n        }\n        const userBaseDir = this._oni.configuration.getValue<string>(\"oni.bookmarks.baseDirectory\")\n        const baseDir = userBaseDir || homedir()\n        return path.join(baseDir, bookmark)\n    }\n\n    public handleBookmark = async ({ metadata }: Menu.MenuOption) => {\n        const bookmarkPath = this._getBookmarkPath(metadata.path)\n        await this._handleItem(bookmarkPath)\n    }\n\n    // deliberately throw errors as a means of clarifying if a path exists\n    // i.e. if isDir => true, else => false, if does not exist => new Error(err)\n    public isDir = async (path: string) => {\n        const stats = await stat(path)\n        return stats.isDirectory()\n    }\n\n    private _handleItem = async (bookmarkPath: string) => {\n        try {\n            const isDirectory = await this.isDir(bookmarkPath)\n            return isDirectory\n                ? this._oni.workspace.changeDirectory(bookmarkPath)\n                : this._oni.editors.openFile(bookmarkPath)\n        } catch (error) {\n            this._oni.log.warn(\n                `[Oni Bookmarks Menu Error]: The Bookmark path ${bookmarkPath} does not exist: \\n ${\n                    error.message\n                }`,\n            )\n        }\n    }\n\n    public cancel(): void {}\n\n    public changeQueryText(newText) {\n        this._onSearchResults.dispatch({\n            items: this._bookmarkItems,\n            isComplete: true,\n        })\n    }\n\n    public get onSearchResults(): IEvent<QuickOpenResult> {\n        return this._onSearchResults\n    }\n}\n"
  },
  {
    "path": "extensions/oni-plugin-quickopen/src/QuickOpen.ts",
    "content": "import { lstatSync } from \"fs\"\n\nimport * as path from \"path\"\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\n\nimport BookmarkSearch from \"./BookmarksSearch\"\nimport { getTypeFromMenuItem, QuickOpenItem, QuickOpenType } from \"./QuickOpenItem\"\n\ntype CreateQuery = (text: string) => Oni.Search.Query\n\nexport interface QuickOpenResult {\n    items: QuickOpenItem[]\n    isComplete: boolean\n}\n\nexport interface IAsyncSearch {\n    cancel(): void\n    changeQueryText(newText): void\n    onSearchResults: IEvent<QuickOpenResult>\n}\n\nclass NullSearch implements IAsyncSearch {\n    private _onSearchResults = new Event<QuickOpenResult>()\n\n    public cancel(): void {\n        return undefined\n    }\n\n    public changeQueryText(newText): void {\n        return undefined\n    }\n\n    public get onSearchResults(): IEvent<QuickOpenResult> {\n        return this._onSearchResults\n    }\n}\n\nclass BufferLinesSearch implements IAsyncSearch {\n    private _onSearchResults = new Event<QuickOpenResult>()\n    private _items: QuickOpenItem[]\n\n    constructor(oni: Oni.Plugin.Api, lines: string[]) {\n        let i = 0\n        this._items = lines.map(\n            s =>\n                new QuickOpenItem(\n                    String(++i),\n                    s,\n                    QuickOpenType.bufferLine,\n                    oni.editors.activeEditor.activeBuffer.filePath,\n                    i,\n                    0,\n                ),\n        )\n    }\n\n    public cancel(): void {}\n\n    public changeQueryText(newText): void {\n        this._onSearchResults.dispatch({\n            items: this._items,\n            isComplete: true,\n        })\n    }\n\n    public get onSearchResults(): IEvent<QuickOpenResult> {\n        return this._onSearchResults\n    }\n}\n\nclass FilePathSearch implements IAsyncSearch {\n    private _activeQuery: Oni.Search.Query\n    private _onSearchResults = new Event<QuickOpenResult>()\n    private _cached = false\n\n    constructor(private _oni: Oni.Plugin.Api) {}\n\n    public cancel(): void {}\n\n    public changeQueryText(newText): void {\n        if (this._cached) {\n            return\n        }\n        this._cached = true\n\n        const activeQuery = this._oni.search.findInPath({\n            searchQuery: null,\n            fileFilter: null,\n            workspace: null,\n        })\n        activeQuery.onSearchResults.subscribe(result => {\n            const items = result.items.map(i => FilePathSearch.toQuickOpenItem(i))\n            this._onSearchResults.dispatch({\n                items,\n                isComplete: result.isComplete,\n            })\n        })\n        activeQuery.start()\n    }\n\n    public get onSearchResults(): IEvent<QuickOpenResult> {\n        return this._onSearchResults\n    }\n\n    private static toQuickOpenItem(item: Oni.Search.ResultItem): QuickOpenItem {\n        return new QuickOpenItem(\n            path.basename(item.fileName),\n            path.dirname(item.fileName),\n            QuickOpenType.file,\n            item.fileName,\n            item.line,\n            item.column,\n        )\n    }\n}\n\nclass FileContentSearch implements IAsyncSearch {\n    private _activeQuery: Oni.Search.Query\n    private _onSearchResults = new Event<QuickOpenResult>()\n\n    constructor(private _oni: Oni.Plugin.Api) {\n        this._activeQuery = this._oni.search.nullSearch\n    }\n\n    public cancel(): void {\n        this._activeQuery.cancel()\n        this._activeQuery = this._oni.search.nullSearch\n    }\n\n    public changeQueryText(newText): void {\n        this._activeQuery.cancel()\n\n        if (!newText || newText.length < 1) {\n            this._onSearchResults.dispatch({\n                items: [],\n                isComplete: true,\n            })\n            return\n        }\n\n        const searchParams = {\n            searchQuery: newText,\n            fileFilter: null,\n            workspace: null,\n        }\n        this._activeQuery = this._oni.search.findInFile(searchParams)\n        this._activeQuery.onSearchResults.subscribe(result => {\n            this._onSearchResults.dispatch({\n                items: result.items.map(i => FileContentSearch.toQuickOpenItem(i)),\n                isComplete: result.isComplete,\n            })\n        })\n        this._activeQuery.start()\n    }\n\n    public get onSearchResults(): IEvent<QuickOpenResult> {\n        return this._onSearchResults\n    }\n\n    private static toQuickOpenItem(item: Oni.Search.ResultItem): QuickOpenItem {\n        return new QuickOpenItem(\n            item.text,\n            path.basename(item.fileName),\n            QuickOpenType.file,\n            item.fileName,\n            item.line,\n            item.column,\n        )\n    }\n}\n\nfunction getHome(): string {\n    return process.env[process.platform === \"win32\" ? \"USERPROFILE\" : \"HOME\"]\n}\n\nexport class QuickOpen {\n    private _menu: Oni.Menu.MenuInstance\n    private _searcher: IAsyncSearch = new NullSearch()\n    private _seenItems: Set<string> = new Set()\n    private _itemsFound: QuickOpenItem[] = []\n    private _bookmarksSearch: BookmarkSearch\n\n    constructor(private _oni: Oni.Plugin.Api) {\n        this._menu = _oni.menu.create()\n\n        this._menu.onHide.subscribe(() => {\n            this._searcher.cancel()\n        })\n\n        this._bookmarksSearch = new BookmarkSearch(this._oni)\n\n        this._menu.onFilterTextChanged.subscribe(newFilter => {\n            if (this._menu.isOpen()) {\n                const timeout = window.setTimeout(() => {\n                    this._menu.setLoading(true)\n                }, 200)\n                this._searcher.changeQueryText(newFilter)\n                if (timeout) {\n                    window.clearTimeout(timeout)\n                }\n            } else {\n                this._searcher.cancel()\n            }\n        })\n\n        this._menu.onItemSelected.subscribe(() => {\n            this.open(this.getDefaultOpenMode())\n        })\n    }\n\n    public isOpen(): boolean {\n        return this._menu.isOpen()\n    }\n\n    public async open(mode: Oni.FileOpenMode): Promise<void> {\n        const selectedItem = this._menu.selectedItem\n        if (!selectedItem) {\n            return\n        }\n\n        const { activeWorkspace } = this._oni.workspace\n        const basePath = activeWorkspace ? [activeWorkspace] : []\n        const pathArgs = basePath.concat([selectedItem.metadata[\"path\"]])\n        const fullPath = path.join(...pathArgs).replace(\"~\", getHome())\n\n        this._seenItems.add(selectedItem.metadata[\"hash\"])\n\n        const qoType = getTypeFromMenuItem(selectedItem)\n        switch (qoType) {\n            case QuickOpenType.bookmarkHelp: {\n                this._oni.commands.executeCommand(\"oni.config.openConfigJs\")\n                break\n            }\n\n            case QuickOpenType.folderHelp: {\n                this._oni.commands.executeCommand(\"workspace.openFolder\")\n                break\n            }\n\n            case QuickOpenType.bufferLine: {\n                if (mode !== Oni.FileOpenMode.Edit) {\n                    const openOptions = { openMode: mode }\n                    const path = this._oni.editors.activeEditor.activeBuffer.filePath\n                    await this._oni.editors.openFile(path, openOptions)\n                }\n                await this._oni.editors.activeEditor.neovim.command(`${selectedItem.label}`)\n                break\n            }\n\n            case QuickOpenType.folder: {\n                this._oni.workspace.changeDirectory(fullPath)\n                break\n            }\n\n            case QuickOpenType.bookmark: {\n                // TODO: add an option to automatically open the quick open menu\n                // Also look at https://github.com/isaacs/node-glob, as a means\n                // of allowing users to specify globs for their bookmarks\n                await this._bookmarksSearch.handleBookmark(selectedItem)\n                break\n            }\n\n            case QuickOpenType.file: {\n                const line = parseInt(selectedItem.metadata[\"line\"], 10)\n                const column = parseInt(selectedItem.metadata[\"column\"], 10)\n\n                const offsetedLine = line > 0 ? line - 1 : 0\n                const offsetedColumn = column > 0 ? column - 1 : 0\n\n                await this._oni.editors.openFile(fullPath, { openMode: mode })\n                await this._oni.editors.activeEditor.activeBuffer.setCursorPosition(\n                    offsetedLine,\n                    offsetedColumn,\n                )\n                break\n            }\n\n            default: {\n                this._oni.log(`Error: unhandled QO type: ${qoType} (${QuickOpenType[qoType]})`)\n                break\n            }\n        }\n\n        this._menu.hide()\n    }\n\n    public setToQuickFix = async () => {\n        this._oni.populateQuickFix(this._itemsFound.map(item => item.toQuickFixItem()))\n        this._menu.hide()\n    }\n\n    public openFileWithAltAction = () => {\n        const mode: Oni.FileOpenMode = this._oni.configuration.getValue(\n            \"editor.quickOpen.alternativeOpenMode\",\n        )\n        this.open(mode)\n    }\n\n    public searchFileByContent = async () => {\n        const filterName = \"none\" // TODO: Use a filter like `regex` (needs a few adjustments)\n        const searcher = new FileContentSearch(this._oni)\n        await this.search(searcher, filterName)\n    }\n\n    public searchFileByPath = async () => {\n        const filterName = this._oni.configuration.getValue<string>(\n            \"editor.quickOpen.filterStrategy\",\n            \"vscode\",\n        )\n        const searchEngine = this.isInstallDirectoryOrHome()\n            ? this._bookmarksSearch\n            : new FilePathSearch(this._oni)\n        await this.search(searchEngine, filterName)\n    }\n\n    public showBufferLines = async () => {\n        const lines = await this._oni.editors.activeEditor.activeBuffer.getLines()\n        await this.search(new BufferLinesSearch(this._oni, lines), \"fuse\")\n    }\n\n    public showBookmarks = async () => {\n        await this.search(this._bookmarksSearch, \"vscode\")\n    }\n\n    private search = async (searcher: IAsyncSearch, filterName: string) => {\n        this._searcher.cancel()\n        const filterFunction = this._oni.filter.getByName(filterName)\n        this._menu.setFilterFunction(filterFunction)\n        this._searcher = searcher\n        searcher.onSearchResults.subscribe(result => {\n            this._itemsFound = result.items\n            if (result.isComplete) {\n                this._menu.setLoading(false)\n            }\n            const pinned = (e: QuickOpenItem) => this._seenItems.has(e.hash)\n            const menuItems = result.items.map(e => e.toMenuItem(this._oni, pinned(e)))\n            this._menu.setItems(menuItems)\n        })\n        this._menu.show()\n        this._searcher.changeQueryText(\"\")\n    }\n\n    private getDefaultOpenMode(): Oni.FileOpenMode {\n        const legacy = this._oni.configuration.getValue(\"editor.quickOpen.defaultOpenMode\", null)\n        // the value of the defaultOpenMode is a numerical enum that includes 0 so we check that the value\n        // is a number and that number is an option in the file open mode enum\n        if (!isNaN(legacy) && legacy in Oni.FileOpenMode) {\n            return legacy\n        }\n\n        const defaultOpenMode = this._oni.configuration.getValue(\n            \"quickOpen.defaultOpenMode\",\n            Oni.FileOpenMode.NewTab,\n        )\n\n        return defaultOpenMode\n    }\n\n    private isInstallDirectoryOrHome() {\n        // Offer to open folder/bookmark (Basically user hasn't opened a folder yet)\n        const cwd = process.cwd()\n        const installationDir = path.dirname(process.execPath)\n        const homeDir = getHome()\n        return cwd === installationDir || cwd === homeDir\n    }\n}\n"
  },
  {
    "path": "extensions/oni-plugin-quickopen/src/QuickOpenItem.ts",
    "content": "import * as path from \"path\"\nimport * as Oni from \"oni-api\"\n\nexport enum QuickOpenType {\n    bookmark,\n    bookmarkHelp,\n    file,\n    folder,\n    folderHelp,\n    bufferLine,\n}\n\nexport function getTypeFromMenuItem(item: Oni.Menu.MenuOption): QuickOpenType {\n    return QuickOpenType[item.metadata[\"qo-type\"]]\n}\n\nexport type IToMenuItem = (qo: QuickOpenItem) => Oni.Menu.MenuOption\n\n// Wrapper around quick open items, this not only allows us to show multiple icons\n// It also allows us to distinguish between types of items\nexport class QuickOpenItem {\n    constructor(\n        private _label: string,\n        private _detail: string,\n        private _type: QuickOpenType,\n        private _path = \"\",\n        private _line = 0,\n        private _column = 0,\n    ) {\n        this._label = _label.trim()\n        this._detail = _detail.trim()\n    }\n\n    public toMenuItem(oni: Oni.Plugin.Api, pinned: boolean): Oni.Menu.MenuOption {\n        return {\n            icon: this.getIcon(oni),\n            label: this._label,\n            detail: this._detail,\n            metadata: {\n                \"qo-type\": QuickOpenType[this._type],\n                hash: this.hash,\n                path: this._path,\n                line: this._line.toString(),\n                column: this._column.toString(),\n            },\n            pinned,\n        }\n    }\n\n    public toQuickFixItem(): Oni.QuickFixEntry {\n        return {\n            filename: this._path,\n            lnum: this._line,\n            col: this._column,\n            text: (this._label + \" \" + this._detail).trim(),\n        }\n    }\n\n    public get hash(): string {\n        return [\n            this._label,\n            this._detail,\n            QuickOpenType[this._type],\n            this._path,\n            String(this._line),\n            String(this._column),\n        ].join(\"|\")\n    }\n\n    private getIcon(oni: Oni.Plugin.Api): any {\n        // Return a fa icon by type\n        switch (this._type) {\n            case QuickOpenType.bookmark:\n                return \"star-o\"\n            case QuickOpenType.bookmarkHelp:\n                return \"info\"\n            case QuickOpenType.file:\n                return oni.ui.getFileIcon(this._label)\n            case QuickOpenType.folder:\n                return \"folder-o\"\n            case QuickOpenType.folderHelp:\n                return \"folder-open-o\"\n            case QuickOpenType.bufferLine:\n                return \"angle-right\"\n            default:\n                return \"question-circle-o\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/oni-plugin-quickopen/src/index.tsx",
    "content": "import * as Oni from \"oni-api\"\n\nimport { QuickOpen } from \"./QuickOpen\"\n\nlet _instance: QuickOpen = null\n\nfunction registerCommands(oni: Oni.Plugin.Api) {\n    const shouldShowMenu = () => {\n        return !oni.menu.isMenuOpen()\n    }\n\n    const isOpen = () => _instance.isOpen()\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.searchFileByContent\",\n        name: null,\n        detail: null,\n        execute: _instance.searchFileByContent,\n        enabled: shouldShowMenu,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.searchFileByPath\",\n        name: null,\n        detail: null,\n        execute: _instance.searchFileByPath,\n        enabled: shouldShowMenu,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.show\",\n        name: null,\n        detail: null,\n        execute: _instance.searchFileByPath,\n        enabled: shouldShowMenu,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.showBookmarks\",\n        name: null,\n        detail: null,\n        execute: _instance.showBookmarks,\n        enabled: shouldShowMenu,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.showBufferLines\",\n        name: null,\n        detail: null,\n        execute: _instance.showBufferLines,\n        enabled: shouldShowMenu,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.openFileNewTab\",\n        name: null,\n        detail: null,\n        execute: () => _instance.open(Oni.FileOpenMode.NewTab),\n        enabled: isOpen,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.openFileAlternative\",\n        name: null,\n        detail: null,\n        execute: _instance.openFileWithAltAction,\n        enabled: isOpen,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.openFileVertical\",\n        name: null,\n        detail: null,\n        execute: () => _instance.open(Oni.FileOpenMode.VerticalSplit),\n        enabled: isOpen,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.openFileHorizontal\",\n        name: null,\n        detail: null,\n        execute: () => _instance.open(Oni.FileOpenMode.HorizontalSplit),\n        enabled: isOpen,\n    })\n\n    oni.commands.registerCommand({\n        command: \"quickOpen.setToQuickFix\",\n        name: null,\n        detail: null,\n        execute: _instance.setToQuickFix,\n        enabled: isOpen,\n    })\n}\n\nexport function activate(oni: Oni.Plugin.Api) {\n    if (!_instance) {\n        _instance = new QuickOpen(oni)\n        registerCommands(oni)\n    }\n\n    return _instance\n}\n"
  },
  {
    "path": "extensions/oni-plugin-quickopen/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"preserveConstEnums\": true,\n        \"outDir\": \"./lib\",\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"declaration\": true,\n        \"sourceMap\": true,\n        \"target\": \"es2015\",\n        \"skipLibCheck\": true\n    },\n    \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "extensions/php/syntaxes/html.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-php/blob/master/grammars/html.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-php/commit/29c140e1531e0b5e842e5bfd4377f879d8b79cd4\",\n    \"name\": \"PHP\",\n    \"scopeName\": \"text.html.php\",\n    \"injections\": {\n        \"text.html.php - (meta.embedded | meta.tag), L:text.html.php meta.tag, L:text.html.php source.js\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#php-tag\"\n                }\n            ]\n        }\n    },\n    \"patterns\": [\n        {\n            \"begin\": \"\\\\A#!\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.php\"\n                }\n            },\n            \"end\": \"$\",\n            \"name\": \"comment.line.shebang.php\"\n        },\n        {\n            \"include\": \"text.html.basic\"\n        }\n    ],\n    \"repository\": {\n        \"php-tag\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"<\\\\?(?i:php|=)?(?![^?]*\\\\?>)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        }\n                    },\n                    \"end\": \"(\\\\?)>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"source.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.block.php\",\n                    \"contentName\": \"source.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.php\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"<\\\\?(?i:php|=)?\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        }\n                    },\n                    \"end\": \"(\\\\?)>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"source.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.line.php\",\n                    \"contentName\": \"source.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.php\"\n                        }\n                    ]\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/php/syntaxes/php.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-php/blob/master/grammars/php.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-php/commit/b054176835218c446d22b3c1b9dcfdcf8cacf49f\",\n    \"scopeName\": \"source.php\",\n    \"patterns\": [\n        {\n            \"include\": \"#comments\"\n        },\n        {\n            \"begin\":\n                \"(?i)^\\\\s*(interface)\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\\\s*(extends)?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.interface.php\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.interface.php\"\n                },\n                \"3\": {\n                    \"name\": \"storage.modifier.extends.php\"\n                }\n            },\n            \"end\":\n                \"(?i)((?:[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\\\\s*,\\\\s*)*)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?\\\\s*(?:(?={)|$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                            \"name\": \"entity.other.inherited-class.php\"\n                        },\n                        {\n                            \"match\": \",\",\n                            \"name\": \"punctuation.separator.classes.php\"\n                        }\n                    ]\n                },\n                \"2\": {\n                    \"name\": \"entity.other.inherited-class.php\"\n                }\n            },\n            \"name\": \"meta.interface.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#namespace\"\n                }\n            ]\n        },\n        {\n            \"begin\":\n                \"(?i)^\\\\s*(trait)\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.trait.php\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.trait.php\"\n                }\n            },\n            \"end\": \"(?={)\",\n            \"name\": \"meta.trait.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                }\n            ]\n        },\n        {\n            \"match\":\n                \"(?i)(?:^|(?<=<\\\\?php))\\\\s*(namespace)\\\\s+([a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]+)(?=\\\\s*;)\",\n            \"name\": \"meta.namespace.php\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.namespace.php\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.namespace.php\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\\",\n                            \"name\": \"punctuation.separator.inheritance.php\"\n                        }\n                    ]\n                }\n            }\n        },\n        {\n            \"begin\": \"(?i)(?:^|(?<=<\\\\?php))\\\\s*(namespace)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.namespace.php\"\n                }\n            },\n            \"end\": \"(?<=})|(?=\\\\?>)\",\n            \"name\": \"meta.namespace.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"match\": \"(?i)[a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]+\",\n                    \"name\": \"entity.name.type.namespace.php\",\n                    \"captures\": {\n                        \"0\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\",\n                                    \"name\": \"punctuation.separator.inheritance.php\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.namespace.begin.bracket.curly.php\"\n                        }\n                    },\n                    \"end\": \"}|(?=\\\\?>)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.namespace.end.bracket.curly.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"[^\\\\s]+\",\n                    \"name\": \"invalid.illegal.identifier.php\"\n                }\n            ]\n        },\n        {\n            \"match\": \"\\\\s+(?=use\\\\b)\"\n        },\n        {\n            \"begin\": \"(?i)\\\\buse\\\\b\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.other.use.php\"\n                }\n            },\n            \"end\": \"(?<=})|(?=;)\",\n            \"name\": \"meta.use.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(const|function)\\\\b\",\n                    \"name\": \"storage.type.${1:/downcase}.php\"\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.use.begin.bracket.curly.php\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.use.end.bracket.curly.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#scope-resolution\"\n                        },\n                        {\n                            \"match\":\n                                \"(?xi)\\n\\\\b(as)\\n\\\\s+(final|abstract|public|private|protected|static)\\n\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.use-as.php\"\n                                },\n                                \"2\": {\n                                    \"name\": \"storage.modifier.php\"\n                                },\n                                \"3\": {\n                                    \"name\": \"entity.other.alias.php\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\":\n                                \"(?xi)\\n\\\\b(as)\\n\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.use-as.php\"\n                                },\n                                \"2\": {\n                                    \"patterns\": [\n                                        {\n                                            \"match\":\n                                                \"^(?:final|abstract|public|private|protected|static)$\",\n                                            \"name\": \"storage.modifier.php\"\n                                        },\n                                        {\n                                            \"match\": \".+\",\n                                            \"name\": \"entity.other.alias.php\"\n                                        }\n                                    ]\n                                }\n                            }\n                        },\n                        {\n                            \"match\":\n                                \"(?i)\\\\b(insteadof)\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.other.use-insteadof.php\"\n                                },\n                                \"2\": {\n                                    \"name\": \"support.class.php\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \";\",\n                            \"name\": \"punctuation.terminator.expression.php\"\n                        },\n                        {\n                            \"include\": \"#use-inner\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#use-inner\"\n                }\n            ]\n        },\n        {\n            \"begin\":\n                \"(?i)(?:^|(?<=}))\\\\s*(?:(abstract|final)\\\\s+)?(class)\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.${1:/downcase}.php\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.class.php\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.class.php\"\n                }\n            },\n            \"end\": \"}|(?=\\\\?>)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.class.end.bracket.curly.php\"\n                }\n            },\n            \"name\": \"meta.class.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"begin\": \"(?i)(extends)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.extends.php\"\n                        }\n                    },\n                    \"contentName\": \"meta.other.inherited-class.php\",\n                    \"end\": \"(?i)(?=[^a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\])\",\n                    \"patterns\": [\n                        {\n                            \"begin\":\n                                \"(?i)(?=\\\\\\\\?[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\\\\\\\\)\",\n                            \"end\":\n                                \"(?i)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?(?=[^a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\])\",\n                            \"endCaptures\": {\n                                \"1\": {\n                                    \"name\": \"entity.other.inherited-class.php\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#namespace\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#class-builtin\"\n                        },\n                        {\n                            \"include\": \"#namespace\"\n                        },\n                        {\n                            \"match\":\n                                \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                            \"name\": \"entity.other.inherited-class.php\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(implements)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.implements.php\"\n                        }\n                    },\n                    \"end\": \"(?i)(?=[;{])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comments\"\n                        },\n                        {\n                            \"begin\": \"(?i)(?=[a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]+)\",\n                            \"contentName\": \"meta.other.inherited-class.php\",\n                            \"end\":\n                                \"(?i)(?:\\\\s*(?:,|(?=[^a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\\\\\s]))\\\\s*)\",\n                            \"patterns\": [\n                                {\n                                    \"begin\":\n                                        \"(?i)(?=\\\\\\\\?[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\\\\\\\\)\",\n                                    \"end\":\n                                        \"(?i)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?(?=[^a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\])\",\n                                    \"endCaptures\": {\n                                        \"1\": {\n                                            \"name\": \"entity.other.inherited-class.php\"\n                                        }\n                                    },\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#namespace\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"include\": \"#class-builtin\"\n                                },\n                                {\n                                    \"include\": \"#namespace\"\n                                },\n                                {\n                                    \"match\":\n                                        \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                                    \"name\": \"entity.other.inherited-class.php\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.class.begin.bracket.curly.php\"\n                        }\n                    },\n                    \"end\": \"(?=}|\\\\?>)\",\n                    \"contentName\": \"meta.class.body.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"include\": \"#switch_statement\"\n        },\n        {\n            \"match\": \"\\\\s*\\\\b(yield\\\\s+from)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.yield-from.php\"\n                }\n            }\n        },\n        {\n            \"match\":\n                \"(?x)\\n\\\\s* # FIXME: Removing this causes specs to fail. Investigate.\\n\\\\b(\\n  break|case|continue|declare|default|die|do|\\n  else(if)?|end(declare|for(each)?|if|switch|while)|exit|\\n  for(each)?|if|return|switch|use|while|yield\\n)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.${1:/downcase}.php\"\n                }\n            }\n        },\n        {\n            \"begin\": \"(?i)\\\\b((?:require|include)(?:_once)?)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.import.include.php\"\n                }\n            },\n            \"end\": \"(?=\\\\s|;|$|\\\\?>)\",\n            \"name\": \"meta.include.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\b(catch)\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.exception.catch.php\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.parameters.begin.bracket.round.php\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.bracket.round.php\"\n                }\n            },\n            \"name\": \"meta.catch.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#namespace\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\n([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)                 # Exception class\\n((?:\\\\s*\\\\|\\\\s*[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)*) # Optional additional exception classes\\n\\\\s*\\n((\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)           # Variable\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.class.exception.php\"\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"match\":\n                                        \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                                    \"name\": \"support.class.exception.php\"\n                                },\n                                {\n                                    \"match\": \"\\\\|\",\n                                    \"name\": \"punctuation.separator.delimiter.php\"\n                                }\n                            ]\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    }\n                }\n            ]\n        },\n        {\n            \"match\": \"\\\\b(catch|try|throw|exception|finally)\\\\b\",\n            \"name\": \"keyword.control.exception.php\"\n        },\n        {\n            \"begin\": \"(?i)\\\\b(function)\\\\s*(?=\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.function.php\"\n                }\n            },\n            \"end\": \"(?={)\",\n            \"name\": \"meta.function.closure.php\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.begin.bracket.round.php\"\n                        }\n                    },\n                    \"contentName\": \"meta.function.parameters.php\",\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.end.bracket.round.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?i)(use)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.function.use.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.parameters.begin.bracket.round.php\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.end.bracket.round.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.php\"\n                                },\n                                \"2\": {\n                                    \"name\": \"storage.modifier.reference.php\"\n                                },\n                                \"3\": {\n                                    \"name\": \"punctuation.definition.variable.php\"\n                                }\n                            },\n                            \"match\":\n                                \"(?i)((&)?\\\\s*(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\\\s*(?=,|\\\\))\",\n                            \"name\": \"meta.function.closure.use.php\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\":\n                \"(?x)\\n((?:(?:final|abstract|public|private|protected|static)\\\\s+)*)\\n(function)\\\\s+\\n(?i:\\n  (__(?:call|construct|debugInfo|destruct|get|set|isset|unset|toString|\\n        clone|set_state|sleep|wakeup|autoload|invoke|callStatic))\\n  |([a-zA-Z_\\\\x{7f}-\\\\x{7fffffff}][a-zA-Z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\n)\\n\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"match\": \"final|abstract|public|private|protected|static\",\n                            \"name\": \"storage.modifier.php\"\n                        }\n                    ]\n                },\n                \"2\": {\n                    \"name\": \"storage.type.function.php\"\n                },\n                \"3\": {\n                    \"name\": \"support.function.magic.php\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.function.php\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.parameters.begin.bracket.round.php\"\n                }\n            },\n            \"contentName\": \"meta.function.parameters.php\",\n            \"end\":\n                \"(\\\\))(?:\\\\s*(:)\\\\s*(\\\\?)?\\\\s*([a-zA-Z_\\\\x{7f}-\\\\x{7fffffff}][a-zA-Z0-9_\\\\x{7f}-\\\\x{7fffffff}]*))?\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.parameters.end.bracket.round.php\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.return-value.php\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.operator.nullable-type.php\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.php\"\n                }\n            },\n            \"name\": \"meta.function.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-parameters\"\n                }\n            ]\n        },\n        {\n            \"include\": \"#invoke-call\"\n        },\n        {\n            \"include\": \"#scope-resolution\"\n        },\n        {\n            \"include\": \"#variables\"\n        },\n        {\n            \"include\": \"#strings\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"support.function.construct.php\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.array.begin.bracket.round.php\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.array.end.bracket.round.php\"\n                }\n            },\n            \"match\": \"(array)(\\\\()(\\\\))\",\n            \"name\": \"meta.array.empty.php\"\n        },\n        {\n            \"begin\": \"(array)\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"support.function.construct.php\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.array.begin.bracket.round.php\"\n                }\n            },\n            \"end\": \"\\\\)|(?=\\\\?>)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.array.end.bracket.round.php\"\n                }\n            },\n            \"name\": \"meta.array.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"match\":\n                \"(?i)(\\\\()\\\\s*(array|real|double|float|int(?:eger)?|bool(?:ean)?|string|object|binary|unset)\\\\s*(\\\\))\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.storage-type.begin.bracket.round.php\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.php\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.storage-type.end.bracket.round.php\"\n                }\n            }\n        },\n        {\n            \"match\":\n                \"(?i)\\\\b(array|real|double|float|int(eger)?|bool(ean)?|string|class|var|function|interface|trait|parent|self|object)\\\\b\",\n            \"name\": \"storage.type.php\"\n        },\n        {\n            \"match\":\n                \"(?i)\\\\b(global|abstract|const|extends|implements|final|private|protected|public|static)\\\\b\",\n            \"name\": \"storage.modifier.php\"\n        },\n        {\n            \"include\": \"#object\"\n        },\n        {\n            \"match\": \";\",\n            \"name\": \"punctuation.terminator.expression.php\"\n        },\n        {\n            \"match\": \":\",\n            \"name\": \"punctuation.terminator.statement.php\"\n        },\n        {\n            \"include\": \"#heredoc\"\n        },\n        {\n            \"include\": \"#numbers\"\n        },\n        {\n            \"match\": \"(?i)\\\\bclone\\\\b\",\n            \"name\": \"keyword.other.clone.php\"\n        },\n        {\n            \"match\": \"\\\\.=?\",\n            \"name\": \"keyword.operator.string.php\"\n        },\n        {\n            \"match\": \"=>\",\n            \"name\": \"keyword.operator.key.php\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.assignment.php\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.reference.php\"\n                },\n                \"3\": {\n                    \"name\": \"storage.modifier.reference.php\"\n                }\n            },\n            \"match\": \"(?i)(\\\\=)(&)|(&)(?=[$a-z_])\"\n        },\n        {\n            \"match\": \"@\",\n            \"name\": \"keyword.operator.error-control.php\"\n        },\n        {\n            \"match\": \"===|==|!==|!=|<>\",\n            \"name\": \"keyword.operator.comparison.php\"\n        },\n        {\n            \"match\": \"=|\\\\+=|\\\\-=|\\\\*=|/=|%=|&=|\\\\|=|\\\\^=|<<=|>>=\",\n            \"name\": \"keyword.operator.assignment.php\"\n        },\n        {\n            \"match\": \"<=>|<=|>=|<|>\",\n            \"name\": \"keyword.operator.comparison.php\"\n        },\n        {\n            \"match\": \"\\\\-\\\\-|\\\\+\\\\+\",\n            \"name\": \"keyword.operator.increment-decrement.php\"\n        },\n        {\n            \"match\": \"\\\\-|\\\\+|\\\\*|/|%\",\n            \"name\": \"keyword.operator.arithmetic.php\"\n        },\n        {\n            \"match\": \"(?i)(!|&&|\\\\|\\\\|)|\\\\b(and|or|xor|as)\\\\b\",\n            \"name\": \"keyword.operator.logical.php\"\n        },\n        {\n            \"include\": \"#function-call\"\n        },\n        {\n            \"match\": \"<<|>>|~|\\\\^|&|\\\\|\",\n            \"name\": \"keyword.operator.bitwise.php\"\n        },\n        {\n            \"begin\": \"(?i)\\\\b(instanceof)\\\\s+(?=[\\\\\\\\$a-z_])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.type.php\"\n                }\n            },\n            \"end\": \"(?=[^\\\\\\\\$a-z0-9_\\\\x{7f}-\\\\x{7fffffff}])\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-name\"\n                },\n                {\n                    \"include\": \"#variable-name\"\n                }\n            ]\n        },\n        {\n            \"include\": \"#instantiation\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.goto.php\"\n                },\n                \"2\": {\n                    \"name\": \"support.other.php\"\n                }\n            },\n            \"match\": \"(?i)(goto)\\\\s+([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.goto-label.php\"\n                }\n            },\n            \"match\":\n                \"(?i)^\\\\s*([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\\\s*:(?!:)\"\n        },\n        {\n            \"include\": \"#string-backtick\"\n        },\n        {\n            \"include\": \"#ternary_shorthand\"\n        },\n        {\n            \"include\": \"#null_coalescing\"\n        },\n        {\n            \"include\": \"#ternary_expression\"\n        },\n        {\n            \"begin\": \"{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.begin.bracket.curly.php\"\n                }\n            },\n            \"end\": \"}|(?=\\\\?>)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.end.bracket.curly.php\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.array.begin.php\"\n                }\n            },\n            \"end\": \"\\\\]|(?=\\\\?>)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.array.end.php\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.begin.bracket.round.php\"\n                }\n            },\n            \"end\": \"\\\\)|(?=\\\\?>)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.end.bracket.round.php\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"include\": \"#constants\"\n        },\n        {\n            \"match\": \",\",\n            \"name\": \"punctuation.separator.delimiter.php\"\n        }\n    ],\n    \"repository\": {\n        \"class-builtin\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?xi)\\n(\\\\\\\\)?\\\\b\\n((APC|Append)Iterator|Array(Access|Iterator|Object)\\n|Bad(Function|Method)CallException\\n|(Caching|CallbackFilter)Iterator|Collator|Collectable|Cond|Countable|CURLFile\\n|Date(Interval|Period|Time(Interface|Immutable|Zone)?)?|Directory(Iterator)?|DomainException\\n|DOM(Attr|CdataSection|CharacterData|Comment|Document(Fragment)?|Element|EntityReference\\n    |Implementation|NamedNodeMap|Node(list)?|ProcessingInstruction|Text|XPath)\\n|(Error)?Exception|EmptyIterator\\n|finfo\\n|Ev(Check|Child|Embed|Fork|Idle|Io|Loop|Periodic|Prepare|Signal|Stat|Timer|Watcher)?\\n|Event(Base|Buffer(Event)?|SslContext|Http(Request|Connection)?|Config|DnsBase|Util|Listener)?\\n|FANNConnection|(Filter|Filesystem)Iterator\\n|Gender\\\\\\\\Gender|GlobIterator|Gmagick(Draw|Pixel)?\\n|Haru(Annotation|Destination|Doc|Encoder|Font|Image|Outline|Page)\\n|Http((Inflate|Deflate)?Stream|Message|Request(Pool)?|Response|QueryString)\\n|HRTime\\\\\\\\(PerformanceCounter|StopWatch)\\n|Intl(Calendar|((CodePoint|RuleBased)?Break|Parts)?Iterator|DateFormatter|TimeZone)\\n|Imagick(Draw|Pixel(Iterator)?)?\\n|InfiniteIterator|InvalidArgumentException|Iterator(Aggregate|Iterator)?\\n|JsonSerializable\\n|KTaglib_(MPEG_(File|AudioProperties)|Tag|ID3v2_(Tag|(AttachedPicture)?Frame))\\n|Lapack|(Length|Locale|Logic)Exception|LimitIterator|Lua(Closure)?\\n|Mongo(BinData|Client|Code|Collection|CommandCursor|Cursor(Exception)?|Date|DB(Ref)?|DeleteBatch\\n      |Grid(FS(Cursor|File)?)|Id|InsertBatch|Int(32|64)|Log|Pool|Regex|ResultException|Timestamp\\n      |UpdateBatch|Write(Batch|ConcernException))?\\n|Memcache(d)?|MessageFormatter|MultipleIterator|Mutex\\n|mysqli(_(driver|stmt|warning|result))?\\n|MysqlndUh(Connection|PreparedStatement)\\n|NoRewindIterator|Normalizer|NumberFormatter\\n|OCI-(Collection|Lob)|OuterIterator|(OutOf(Bounds|Range)|Overflow)Exception\\n|ParentIterator|PDO(Statement)?|Phar(Data|FileInfo)?|php_user_filter|Pool\\n|QuickHash(Int(Set|StringHash)|StringIntHash)\\n|Recursive(Array|Caching|Directory|Fallback|Filter|Iterator|Regex|Tree)?Iterator\\n|Reflection(Class|Function(Abstract)?|Method|Object|Parameter|Property|(Zend)?Extension)?\\n|RangeException|Reflector|RegexIterator|ResourceBundle|RuntimeException|RRD(Creator|Graph|Updater)\\n|SAM(Connection|Message)|SCA(_(SoapProxy|LocalProxy))?\\n|SDO_(DAS_(ChangeSummary|Data(Factory|Object)|Relational|Setting|XML(_Document)?)\\n     |Data(Factory|Object)|Exception|List|Model_(Property|ReflectionDataObject|Type)|Sequence)\\n|SeekableIterator|Serializable|SessionHandler(Interface)?|SimpleXML(Iterator|Element)|SNMP\\n|Soap(Client|Fault|Header|Param|Server|Var)\\n|SphinxClient|Spoofchecker\\n|Spl(DoublyLinkedList|Enum|File(Info|Object)|FixedArray|(Max|Min)?Heap|Observer|ObjectStorage\\n    |(Priority)?Queue|Stack|Subject|Type|TempFileObject)\\n|SQLite(3(Result|Stmt)?|Database|Result|Unbuffered)\\n|stdClass|streamWrapper|SVM(Model)?|Swish(Result(s)?|Search)?|Sync(Event|Mutex|ReaderWriter|Semaphore)\\n|Thread(ed)?|tidy(Node)?|TokyoTyrant(Table|Iterator|Query)?|Transliterator|Traversable\\n|UConverter|(Underflow|UnexpectedValue)Exception\\n|V8Js(Exception)?|Varnish(Admin|Log|Stat)\\n|Worker|Weak(Map|Ref)\\n|XML(Diff\\\\\\\\(Base|DOM|File|Memory)|Reader|Writer)|XsltProcessor\\n|Yaf_(Route_(Interface|Map|Regex|Rewrite|Simple|Supervar)\\n     |Action_Abstract|Application|Config_(Simple|Ini|Abstract)|Controller_Abstract\\n     |Dispatcher|Exception|Loader|Plugin_Abstract|Registry|Request_(Abstract|Simple|Http)\\n     |Response_Abstract|Router|Session|View_(Simple|Interface))\\n|Yar_(Client(_Exception)?|Concurrent_Client|Server(_Exception)?)\\n|ZipArchive|ZMQ(Context|Device|Poll|Socket)?)\\n\\\\b\",\n                    \"name\": \"support.class.builtin.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.inheritance.php\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"class-name\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?i)(?=\\\\\\\\?[a-z_0-9]+\\\\\\\\)\",\n                    \"end\": \"(?i)([a-z_][a-z_0-9]*)?(?![a-z0-9_\\\\\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.class.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#namespace\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#class-builtin\"\n                },\n                {\n                    \"begin\": \"(?=[\\\\\\\\a-zA-Z_])\",\n                    \"end\": \"(?i)([a-z_][a-z_0-9]*)?(?![a-z0-9_\\\\\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.class.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#namespace\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"comments\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"/\\\\*\\\\*(?=\\\\s)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.php\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.php\"\n                        }\n                    },\n                    \"name\": \"comment.block.documentation.phpdoc.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#php_doc\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"/\\\\*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.php\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"name\": \"comment.block.php\"\n                },\n                {\n                    \"begin\": \"(^\\\\s+)?(?=//)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.php\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"//\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.php\"\n                                }\n                            },\n                            \"end\": \"\\\\n|(?=\\\\?>)\",\n                            \"name\": \"comment.line.double-slash.php\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(^\\\\s+)?(?=#)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.php\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"#\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.php\"\n                                }\n                            },\n                            \"end\": \"\\\\n|(?=\\\\?>)\",\n                            \"name\": \"comment.line.number-sign.php\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"constants\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?i)\\\\b(TRUE|FALSE|NULL|__(FILE|DIR|FUNCTION|CLASS|METHOD|LINE|NAMESPACE)__|ON|OFF|YES|NO|NL|BR|TAB)\\\\b\",\n                    \"name\": \"constant.language.php\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\\\\\\\)?\\\\b\\n(DEFAULT_INCLUDE_PATH\\n|EAR_(INSTALL|EXTENSION)_DIR\\n|E_(ALL|COMPILE_(ERROR|WARNING)|CORE_(ERROR|WARNING)|DEPRECATED|ERROR|NOTICE\\n   |PARSE|RECOVERABLE_ERROR|STRICT|USER_(DEPRECATED|ERROR|NOTICE|WARNING)|WARNING)\\n|PHP_(ROUND_HALF_(DOWN|EVEN|ODD|UP)|(MAJOR|MINOR|RELEASE)_VERSION|MAXPATHLEN\\n     |BINDIR|SHLIB_SUFFIX|SYSCONFDIR|SAPI|CONFIG_FILE_(PATH|SCAN_DIR)\\n     |INT_(MAX|SIZE)|ZTS|OS|OUTPUT_HANDLER_(START|CONT|END)|DEBUG|DATADIR\\n     |URL_(SCHEME|HOST|USER|PORT|PASS|PATH|QUERY|FRAGMENT)|PREFIX\\n     |EXTRA_VERSION|EXTENSION_DIR|EOL|VERSION(_ID)?\\n     |WINDOWS_(NT_(SERVER|DOMAIN_CONTROLLER|WORKSTATION)\\n              |VERSION_(MAJOR|MINOR)|BUILD|SUITEMASK|SP_(MAJOR|MINOR)\\n              |PRODUCTTYPE|PLATFORM)\\n     |LIBDIR|LOCALSTATEDIR)\\n|STD(ERR|IN|OUT)|ZEND_(DEBUG_BUILD|THREAD_SAFE))\\n\\\\b\",\n                    \"name\": \"support.constant.core.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.inheritance.php\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\\\\\\\)?\\\\b\\n(__COMPILER_HALT_OFFSET__|AB(MON_(1|2|3|4|5|6|7|8|9|10|11|12)|DAY[1-7])\\n|AM_STR|ASSERT_(ACTIVE|BAIL|CALLBACK_QUIET_EVAL|WARNING)|ALT_DIGITS\\n|CASE_(UPPER|LOWER)|CHAR_MAX|CONNECTION_(ABORTED|NORMAL|TIMEOUT)|CODESET|COUNT_(NORMAL|RECURSIVE)\\n|CREDITS_(ALL|DOCS|FULLPAGE|GENERAL|GROUP|MODULES|QA|SAPI)\\n|CRYPT_(BLOWFISH|EXT_DES|MD5|SHA(256|512)|SALT_LENGTH|STD_DES)|CURRENCY_SYMBOL\\n|D_(T_)?FMT|DATE_(ATOM|COOKIE|ISO8601|RFC(822|850|1036|1123|2822|3339)|RSS|W3C)\\n|DAY_[1-7]|DECIMAL_POINT|DIRECTORY_SEPARATOR\\n|ENT_(COMPAT|IGNORE|(NO)?QUOTES)|EXTR_(IF_EXISTS|OVERWRITE|PREFIX_(ALL|IF_EXISTS|INVALID|SAME)|REFS|SKIP)\\n|ERA(_(D_(T_)?FMT)|T_FMT|YEAR)?|FRAC_DIGITS|GROUPING|HASH_HMAC|HTML_(ENTITIES|SPECIALCHARS)\\n|INF|INFO_(ALL|CREDITS|CONFIGURATION|ENVIRONMENT|GENERAL|LICENSEMODULES|VARIABLES)\\n|INI_(ALL|CANNER_(NORMAL|RAW)|PERDIR|SYSTEM|USER)|INT_(CURR_SYMBOL|FRAC_DIGITS)\\n|LC_(ALL|COLLATE|CTYPE|MESSAGES|MONETARY|NUMERIC|TIME)|LOCK_(EX|NB|SH|UN)\\n|LOG_(ALERT|AUTH(PRIV)?|CRIT|CRON|CONS|DAEMON|DEBUG|EMERG|ERR|INFO|LOCAL[1-7]|LPR|KERN|MAIL\\n     |NEWS|NODELAY|NOTICE|NOWAIT|ODELAY|PID|PERROR|WARNING|SYSLOG|UCP|USER)\\n|M_(1_PI|SQRT(1_2|2|3|PI)|2_(SQRT)?PI|PI(_(2|4))?|E(ULER)?|LN(10|2|PI)|LOG(10|2)E)\\n|MON_(1|2|3|4|5|6|7|8|9|10|11|12|DECIMAL_POINT|GROUPING|THOUSANDS_SEP)\\n|N_(CS_PRECEDES|SEP_BY_SPACE|SIGN_POSN)|NAN|NEGATIVE_SIGN|NO(EXPR|STR)\\n|P_(CS_PRECEDES|SEP_BY_SPACE|SIGN_POSN)|PM_STR|POSITIVE_SIGN\\n|PATH(_SEPARATOR|INFO_(EXTENSION|(BASE|DIR|FILE)NAME))|RADIXCHAR\\n|SEEK_(CUR|END|SET)|SORT_(ASC|DESC|LOCALE_STRING|REGULAR|STRING)|STR_PAD_(BOTH|LEFT|RIGHT)\\n|T_FMT(_AMPM)?|THOUSEP|THOUSANDS_SEP\\n|UPLOAD_ERR_(CANT_WRITE|EXTENSION|(FORM|INI)_SIZE|NO_(FILE|TMP_DIR)|OK|PARTIAL)\\n|YES(EXPR|STR))\\n\\\\b\",\n                    \"name\": \"support.constant.std.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.inheritance.php\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\\\\\\\)?\\\\b\\n(GLOB_(MARK|BRACE|NO(SORT|CHECK|ESCAPE)|ONLYDIR|ERR|AVAILABLE_FLAGS)\\n|XML_(SAX_IMPL|(DTD|DOCUMENT(_(FRAG|TYPE))?|HTML_DOCUMENT|NOTATION|NAMESPACE_DECL|PI|COMMENT|DATA_SECTION|TEXT)_NODE\\n     |OPTION_(SKIP_(TAGSTART|WHITE)|CASE_FOLDING|TARGET_ENCODING)\\n     |ERROR_((BAD_CHAR|(ATTRIBUTE_EXTERNAL|BINARY|PARAM|RECURSIVE)_ENTITY)_REF|MISPLACED_XML_PI|SYNTAX|NONE\\n            |NO_(MEMORY|ELEMENTS)|TAG_MISMATCH|INCORRECT_ENCODING|INVALID_TOKEN|DUPLICATE_ATTRIBUTE\\n            |UNCLOSED_(CDATA_SECTION|TOKEN)|UNDEFINED_ENTITY|UNKNOWN_ENCODING|JUNK_AFTER_DOC_ELEMENT\\n            |PARTIAL_CHAR|EXTERNAL_ENTITY_HANDLING|ASYNC_ENTITY)\\n     |ENTITY_(((REF|DECL)_)?NODE)|ELEMENT(_DECL)?_NODE|LOCAL_NAMESPACE|ATTRIBUTE_(NMTOKEN(S)?|NOTATION|NODE)\\n     |CDATA|ID(REF(S)?)?|DECL_NODE|ENTITY|ENUMERATION)\\n|MHASH_(RIPEMD(128|160|256|320)|GOST|MD(2|4|5)|SHA(1|224|256|384|512)|SNEFRU256|HAVAL(128|160|192|224|256)\\n       |CRC23(B)?|TIGER(128|160)?|WHIRLPOOL|ADLER32)\\n|MYSQL_(BOTH|NUM|CLIENT_(SSL|COMPRESS|IGNORE_SPACE|INTERACTIVE|ASSOC))\\n|MYSQLI_(REPORT_(STRICT|INDEX|OFF|ERROR|ALL)|REFRESH_(GRANT|MASTER|BACKUP_LOG|STATUS|SLAVE|HOSTS|THREADS|TABLES|LOG)\\n        |READ_DEFAULT_(FILE|GROUP)|(GROUP|MULTIPLE_KEY|BINARY|BLOB)_FLAG|BOTH\\n        |STMT_ATTR_(CURSOR_TYPE|UPDATE_MAX_LENGTH|PREFETCH_ROWS)|STORE_RESULT\\n        |SERVER_QUERY_(NO_((GOOD_)?INDEX_USED)|WAS_SLOW)|SET_(CHARSET_NAME|FLAG)\\n        |NO_(DEFAULT_VALUE_FLAG|DATA)|NOT_NULL_FLAG|NUM(_FLAG)?\\n        |CURSOR_TYPE_(READ_ONLY|SCROLLABLE|NO_CURSOR|FOR_UPDATE)\\n        |CLIENT_(SSL|NO_SCHEMA|COMPRESS|IGNORE_SPACE|INTERACTIVE|FOUND_ROWS)\\n        |TYPE_(GEOMETRY|((MEDIUM|LONG|TINY)_)?BLOB|BIT|SHORT|STRING|SET|YEAR|NULL|NEWDECIMAL|NEWDATE|CHAR\\n              |TIME(STAMP)?|TINY|INT24|INTERVAL|DOUBLE|DECIMAL|DATE(TIME)?|ENUM|VAR_STRING|FLOAT|LONG(LONG)?)\\n        |TIME_STAMP_FLAG|INIT_COMMAND|ZEROFILL_FLAG|ON_UPDATE_NOW_FLAG\\n        |OPT_(NET_((CMD|READ)_BUFFER_SIZE)|CONNECT_TIMEOUT|INT_AND_FLOAT_NATIVE|LOCAL_INFILE)\\n        |DEBUG_TRACE_ENABLED|DATA_TRUNCATED|USE_RESULT|(ENUM|(PART|PRI|UNIQUE)_KEY|UNSIGNED)_FLAG\\n        |ASSOC|ASYNC|AUTO_INCREMENT_FLAG)\\n|MCRYPT_(RC(2|6)|RIJNDAEL_(128|192|256)|RAND|GOST|XTEA|MODE_(STREAM|NOFB|CBC|CFB|OFB|ECB)|MARS\\n        |BLOWFISH(_COMPAT)?|SERPENT|SKIPJACK|SAFER(64|128|PLUS)|CRYPT|CAST_(128|256)|TRIPLEDES|THREEWAY\\n        |TWOFISH|IDEA|(3)?DES|DECRYPT|DEV_(U)?RANDOM|PANAMA|ENCRYPT|ENIGNA|WAKE|LOKI97|ARCFOUR(_IV)?)\\n|STREAM_(REPORT_ERRORS|MUST_SEEK|MKDIR_RECURSIVE|BUFFER_(NONE|FULL|LINE)|SHUT_(RD)?WR\\n        |SOCK_(RDM|RAW|STREAM|SEQPACKET|DGRAM)|SERVER_(BIND|LISTEN)\\n        |NOTIFY_(REDIRECTED|RESOLVE|MIME_TYPE_IS|SEVERITY_(INFO|ERR|WARN)|COMPLETED|CONNECT|PROGRESS\\n                |FILE_SIZE_IS|FAILURE|AUTH_(REQUIRED|RESULT))\\n        |CRYPTO_METHOD_((SSLv2(3)?|SSLv3|TLS)_(CLIENT|SERVER))|CLIENT_((ASYNC_)?CONNECT|PERSISTENT)\\n        |CAST_(AS_STREAM|FOR_SELECT)|(IGNORE|IS)_URL|IPPROTO_(RAW|TCP|ICMP|IP|UDP)|OOB\\n        |OPTION_(READ_(BUFFER|TIMEOUT)|BLOCKING|WRITE_BUFFER)|URL_STAT_(LINK|QUIET)|USE_PATH\\n        |PEEK|PF_(INET(6)?|UNIX)|ENFORCE_SAFE_MODE|FILTER_(ALL|READ|WRITE))\\n|SUNFUNCS_RET_(DOUBLE|STRING|TIMESTAMP)\\n|SQLITE_(READONLY|ROW|MISMATCH|MISUSE|BOTH|BUSY|SCHEMA|NOMEM|NOTFOUND|NOTADB|NOLFS|NUM|CORRUPT\\n        |CONSTRAINT|CANTOPEN|TOOBIG|INTERRUPT|INTERNAL|IOERR|OK|DONE|PROTOCOL|PERM|ERROR|EMPTY\\n        |FORMAT|FULL|LOCKED|ABORT|ASSOC|AUTH)\\n|SQLITE3_(BOTH|BLOB|NUM|NULL|TEXT|INTEGER|OPEN_(READ(ONLY|WRITE)|CREATE)|FLOAT_ASSOC)\\n|CURL(M_(BAD_((EASY)?HANDLE)|CALL_MULTI_PERFORM|INTERNAL_ERROR|OUT_OF_MEMORY|OK)\\n     |MSG_DONE|SSH_AUTH_(HOST|NONE|DEFAULT|PUBLICKEY|PASSWORD|KEYBOARD)\\n     |CLOSEPOLICY_(SLOWEST|CALLBACK|OLDEST|LEAST_(RECENTLY_USED|TRAFFIC)\\n     |INFO_(REDIRECT_(COUNT|TIME)|REQUEST_SIZE|SSL_VERIFYRESULT|STARTTRANSFER_TIME\\n           |(SIZE|SPEED)_(DOWNLOAD|UPLOAD)|HTTP_CODE|HEADER_(OUT|SIZE)|NAMELOOKUP_TIME\\n           |CONNECT_TIME|CONTENT_(TYPE|LENGTH_(DOWNLOAD|UPLOAD))|CERTINFO|TOTAL_TIME\\n           |PRIVATE|PRETRANSFER_TIME|EFFECTIVE_URL|FILETIME)\\n     |OPT_(RESUME_FROM|RETURNTRANSFER|REDIR_PROTOCOLS|REFERER|READ(DATA|FUNCTION)|RANGE|RANDOM_FILE\\n          |MAX(CONNECTS|REDIRS)|BINARYTRANSFER|BUFFERSIZE\\n          |SSH_(HOST_PUBLIC_KEY_MD5|(PRIVATE|PUBLIC)_KEYFILE)|AUTH_TYPES)\\n          |SSL(CERT(TYPE|PASSWD)?|ENGINE(_DEFAULT)?|VERSION|KEY(TYPE|PASSWD)?)\\n          |SSL_(CIPHER_LIST|VERIFY(HOST|PEER))\\n          |STDERR|HTTP(GET|HEADER|200ALIASES|_VERSION|PROXYTUNNEL|AUTH)\\n          |HEADER(FUNCTION)?|NO(BODY|SIGNAL|PROGRESS)|NETRC|CRLF|CONNECTTIMEOUT(_MS)?\\n          |COOKIE(SESSION|JAR|FILE)?|CUSTOMREQUEST|CERTINFO|CLOSEPOLICY|CA(INFO|PATH)|TRANSFERTEXT\\n          |TCP_NODELAY|TIME(CONDITION|OUT(_MS)?|VALUE)|INTERFACE|INFILE(SIZE)?|IPRESOLVE\\n          |DNS_(CACHE_TIMEOUT|USE_GLOBAL_CACHE)|URL|USER(AGENT|PWD)|UNRESTRICTED_AUTH|UPLOAD\\n          |PRIVATE|PROGRESSFUNCTION|PROXY(TYPE|USERPWD|PORT|AUTH)?|PROTOCOLS|PORT\\n          |POST(REDIR|QUOTE|FIELDS)?|PUT|EGDSOCKET|ENCODING|VERBOSE|KRB4LEVEL|KEYPASSWD|QUOTE|FRESH_CONNECT\\n          |FTP(APPEND|LISTONLY|PORT|SSLAUTH)\\n          |FTP_(SSL|SKIP_PASV_IP|CREATE_MISSING_DIRS|USE_EP(RT|SV)|FILEMETHOD)\\n          |FILE(TIME)?|FORBID_REUSE|FOLLOWLOCATION|FAILONERROR|WRITE(FUNCTION|HEADER)|LOW_SPEED_(LIMIT|TIME)\\n          |AUTOREFERER)\\n     |PROXY_(HTTP|SOCKS(4|5))|PROTO_(SCP|SFTP|HTTP(S)?|TELNET|TFTP|DICT|FTP(S)?|FILE|LDAP(S)?|ALL)\\n     |E_((RECV|READ)_ERROR|GOT_NOTHING|MALFORMAT_USER\\n        |BAD_(CONTENT_ENCODING|CALLING_ORDER|PASSWORD_ENTERED|FUNCTION_ARGUMENT)\\n        |SSH|SSL_(CIPHER|CONNECT_ERROR|CERTPROBLEM|CACERT|PEER_CERTIFICATE|ENGINE_(NOTFOUND|SETFAILED))\\n        |SHARE_IN_USE|SEND_ERROR|HTTP_(RANGE_ERROR|NOT_FOUND|PORT_FAILED|POST_ERROR)\\n        |COULDNT_(RESOLVE_(HOST|PROXY)|CONNECT)|TOO_MANY_REDIRECTS|TELNET_OPTION_SYNTAX|OBSOLETE\\n        |OUT_OF_MEMORY|OPERATION|TIMEOUTED|OK|URL_MALFORMAT(_USER)?|UNSUPPORTED_PROTOCOL\\n        |UNKNOWN_TELNET_OPTION|PARTIAL_FILE\\n        |FTP_(BAD_DOWNLOAD_RESUME|SSL_FAILED|COULDNT_(RETR_FILE|GET_SIZE|STOR_FILE|SET_(BINARY|ASCII)|USE_REST)\\n             |CANT_(GET_HOST|RECONNECT)|USER_PASSWORD_INCORRECT|PORT_FAILED|QUOTE_ERROR|WRITE_ERROR\\n             |WEIRD_((PASS|PASV|SERVER|USER)_REPLY|227_FORMAT)|ACCESS_DENIED)\\n        |FILESIZE_EXCEEDED|FILE_COULDNT_READ_FILE|FUNCTION_NOT_FOUND|FAILED_INIT|WRITE_ERROR|LIBRARY_NOT_FOUND\\n        |LDAP_(SEARCH_FAILED|CANNOT_BIND|INVALID_URL)|ABORTED_BY_CALLBACK)\\n     |VERSION_NOW\\n     |FTP(METHOD_(MULTI|SINGLE|NO)CWD|SSL_(ALL|NONE|CONTROL|TRY)|AUTH_(DEFAULT|SSL|TLS))\\n     |AUTH_(ANY(SAFE)?|BASIC|DIGEST|GSSNEGOTIATE|NTLM))\\n|CURL_(HTTP_VERSION_(1_(0|1)|NONE)|NETRC_(REQUIRED|IGNORED|OPTIONAL)|TIMECOND_(IF(UN)?MODSINCE|LASTMOD)\\n      |IPRESOLVE_(V(4|6)|WHATEVER)|VERSION_(SSL|IPV6|KERBEROS4|LIBZ))\\n|IMAGETYPE_(GIF|XBM|BMP|SWF|COUNT|TIFF_(MM|II)|ICO|IFF|UNKNOWN|JB2|JPX|JP2|JPC|JPEG(2000)?|PSD|PNG|WBMP)\\n|INPUT_(REQUEST|GET|SERVER|SESSION|COOKIE|POST|ENV)|ICONV_(MIME_DECODE_(STRICT|CONTINUE_ON_ERROR)|IMPL|VERSION)\\n|DNS_(MX|SRV|SOA|HINFO|NS|NAPTR|CNAME|TXT|PTR|ANY|ALL|AAAA|A(6)?)\\n|DOM(STRING_SIZE_ERR)\\n|DOM_((SYNTAX|HIERARCHY_REQUEST|NO_(MODIFICATION_ALLOWED|DATA_ALLOWED)|NOT_(FOUND|SUPPORTED)|NAMESPACE\\n     |INDEX_SIZE|USE_ATTRIBUTE|VALID_(MODIFICATION|STATE|CHARACTER|ACCESS)|PHP|VALIDATION|WRONG_DOCUMENT)_ERR)\\n|JSON_(HEX_(TAG|QUOT|AMP|APOS)|NUMERIC_CHECK|ERROR_(SYNTAX|STATE_MISMATCH|NONE|CTRL_CHAR|DEPTH|UTF8)|FORCE_OBJECT)\\n|PREG_((D_UTF8(_OFFSET)?|NO|INTERNAL|(BACKTRACK|RECURSION)_LIMIT)_ERROR|GREP_INVERT\\n      |SPLIT_(NO_EMPTY|(DELIM|OFFSET)_CAPTURE)|SET_ORDER|OFFSET_CAPTURE|PATTERN_ORDER)\\n|PSFS_(PASS_ON|ERR_FATAL|FEED_ME|FLAG_(NORMAL|FLUSH_(CLOSE|INC)))\\n|PCRE_VERSION|POSIX_((F|R|W|X)_OK|S_IF(REG|BLK|SOCK|CHR|IFO))\\n|FNM_(NOESCAPE|CASEFOLD|PERIOD|PATHNAME)\\n|FILTER_(REQUIRE_(SCALAR|ARRAY)|NULL_ON_FAILURE|CALLBACK|DEFAULT|UNSAFE_RAW\\n        |SANITIZE_(MAGIC_QUOTES|STRING|STRIPPED|SPECIAL_CHARS|NUMBER_(INT|FLOAT)|URL\\n                  |EMAIL|ENCODED|FULL_SPCIAL_CHARS)\\n        |VALIDATE_(REGEXP|BOOLEAN|INT|IP|URL|EMAIL|FLOAT)\\n        |FORCE_ARRAY\\n        |FLAG_(SCHEME_REQUIRED|STRIP_(BACKTICK|HIGH|LOW)|HOST_REQUIRED|NONE|NO_(RES|PRIV)_RANGE|ENCODE_QUOTES\\n              |IPV(4|6)|PATH_REQUIRED|EMPTY_STRING_NULL|ENCODE_(HIGH|LOW|AMP)|QUERY_REQUIRED\\n              |ALLOW_(SCIENTIFIC|HEX|THOUSAND|OCTAL|FRACTION)))\\n|FILE_(BINARY|SKIP_EMPTY_LINES|NO_DEFAULT_CONTEXT|TEXT|IGNORE_NEW_LINES|USE_INCLUDE_PATH|APPEND)\\n|FILEINFO_(RAW|MIME(_(ENCODING|TYPE))?|SYMLINK|NONE|CONTINUE|DEVICES|PRESERVE_ATIME)\\n|FORCE_(DEFLATE|GZIP)\\n|LIBXML_(XINCLUDE|NSCLEAN|NO(XMLDECL|BLANKS|NET|CDATA|ERROR|EMPTYTAG|ENT|WARNING)\\n        |COMPACT|DTD(VALID|LOAD|ATTR)|((DOTTED|LOADED)_)?VERSION|PARSEHUGE|ERR_(NONE|ERROR|FATAL|WARNING)))\\n\\\\b\",\n                    \"name\": \"support.constant.ext.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.inheritance.php\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\\\\\\\)?\\\\b\\n(T_(RETURN|REQUIRE(_ONCE)?|GOTO|GLOBAL|(MINUS|MOD|MUL|XOR)_EQUAL|METHOD_C|ML_COMMENT|BREAK\\n   |BOOL_CAST|BOOLEAN_(AND|OR)|BAD_CHARACTER|SR(_EQUAL)?|STRING(_CAST|VARNAME)?|START_HEREDOC|STATIC\\n   |SWITCH|SL(_EQUAL)?|HALT_COMPILER|NS_(C|SEPARATOR)|NUM_STRING|NEW|NAMESPACE|CHARACTER|COMMENT\\n   |CONSTANT(_ENCAPSED_STRING)?|CONCAT_EQUAL|CONTINUE|CURLY_OPEN|CLOSE_TAG|CLONE|CLASS(_C)?\\n   |CASE|CATCH|TRY|THROW|IMPLEMENTS|ISSET|IS_((GREATER|SMALLER)_OR_EQUAL|(NOT_)?(IDENTICAL|EQUAL))\\n   |INSTANCEOF|INCLUDE(_ONCE)?|INC|INT_CAST|INTERFACE|INLINE_HTML|IF|OR_EQUAL|OBJECT_(CAST|OPERATOR)\\n   |OPEN_TAG(_WITH_ECHO)?|OLD_FUNCTION|DNUMBER|DIR|DIV_EQUAL|DOC_COMMENT|DOUBLE_(ARROW|CAST|COLON)\\n   |DOLLAR_OPEN_CURLY_BRACES|DO|DEC|DECLARE|DEFAULT|USE|UNSET(_CAST)?|PRINT|PRIVATE|PROTECTED|PUBLIC\\n   |PLUS_EQUAL|PAAMAYIM_NEKUDOTAYIM|EXTENDS|EXIT|EMPTY|ENCAPSED_AND_WHITESPACE\\n   |END(SWITCH|IF|DECLARE|FOR(EACH)?|WHILE)|END_HEREDOC|ECHO|EVAL|ELSE(IF)?|VAR(IABLE)?|FINAL|FILE\\n   |FOR(EACH)?|FUNC_C|FUNCTION|WHITESPACE|WHILE|LNUMBER|LIST|LINE|LOGICAL_(AND|OR|XOR)\\n   |ARRAY_(CAST)?|ABSTRACT|AS|AND_EQUAL))\\n\\\\b\",\n                    \"name\": \"support.constant.parser-token.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.inheritance.php\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                    \"name\": \"constant.other.php\"\n                }\n            ]\n        },\n        \"function-parameters\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.php\"\n                },\n                {\n                    \"begin\":\n                        \"(?xi)\\n(?:(\\\\?)\\\\s*)?(array)                                              # Typehint\\n\\\\s+((&)?\\\\s*(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*) # Variable name with possible reference\\n\\\\s*(=)\\\\s*(array)\\\\s*(\\\\()                                        # Default value\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.nullable-type.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.modifier.reference.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.operator.assignment.php\"\n                        },\n                        \"7\": {\n                            \"name\": \"support.function.construct.php\"\n                        },\n                        \"8\": {\n                            \"name\": \"punctuation.definition.array.begin.bracket.round.php\"\n                        }\n                    },\n                    \"contentName\": \"meta.array.php\",\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.array.end.bracket.round.php\"\n                        }\n                    },\n                    \"name\": \"meta.function.parameter.array.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comments\"\n                        },\n                        {\n                            \"include\": \"#strings\"\n                        },\n                        {\n                            \"include\": \"#numbers\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\n(?:(\\\\?)\\\\s*)?(array|callable)                                     # Typehint\\n\\\\s+((&)?\\\\s*(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*) # Variable name with possible reference\\n(?:                                                                # Optional default value\\n  \\\\s*(=)\\\\s*\\n  (?:\\n    (null)\\n    |\\n    (\\\\[)((?>[^\\\\[\\\\]]+|\\\\[\\\\g<8>\\\\])*)(\\\\])\\n    |((?:\\\\S*?\\\\(\\\\))|(?:\\\\S*?))\\n  )\\n)?\\n\\\\s*(?=,|\\\\)|/[/*]|\\\\#|$) # A closing parentheses (end of argument list) or a comma or a comment\",\n                    \"name\": \"meta.function.parameter.array.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.nullable-type.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.modifier.reference.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.operator.assignment.php\"\n                        },\n                        \"7\": {\n                            \"name\": \"constant.language.php\"\n                        },\n                        \"8\": {\n                            \"name\": \"punctuation.section.array.begin.php\"\n                        },\n                        \"9\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parameter-default-types\"\n                                }\n                            ]\n                        },\n                        \"10\": {\n                            \"name\": \"punctuation.section.array.end.php\"\n                        },\n                        \"11\": {\n                            \"name\": \"invalid.illegal.non-null-typehinted.php\"\n                        }\n                    }\n                },\n                {\n                    \"begin\":\n                        \"(?xi)\\n(?:(\\\\?)\\\\s*)?\\n(\\\\\\\\?(?:[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\\\\\\\\)*)                 # Optional namespace\\n([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)                               # Typehinted class name\\n\\\\s+((&)?\\\\s*(\\\\.\\\\.\\\\.)?(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*) # Variable name with possible reference\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.nullable-type.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.other.namespace.php\",\n                            \"patterns\": [\n                                {\n                                    \"match\":\n                                        \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                                    \"name\": \"storage.type.php\"\n                                },\n                                {\n                                    \"match\": \"\\\\\\\\\",\n                                    \"name\": \"punctuation.separator.inheritance.php\"\n                                }\n                            ]\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"storage.modifier.reference.php\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.operator.variadic.php\"\n                        },\n                        \"7\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\)|/[/*]|\\\\#)\",\n                    \"name\": \"meta.function.parameter.typehinted.php\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"=\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.operator.assignment.php\"\n                                }\n                            },\n                            \"end\": \"(?=,|\\\\)|/[/*]|\\\\#)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.reference.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.variadic.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"match\":\n                        \"(?xi)\\n((&)?\\\\s*(\\\\.\\\\.\\\\.)?(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*) # Variable name with possible reference\\n\\\\s*(?=,|\\\\)|/[/*]|\\\\#|$) # A closing parentheses (end of argument list) or a comma or a comment\",\n                    \"name\": \"meta.function.parameter.no-default.php\"\n                },\n                {\n                    \"begin\":\n                        \"(?xi)\\n((&)?\\\\s*(\\\\.\\\\.\\\\.)?(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*) # Variable name with possible reference\\n\\\\s*(=)\\\\s*\\n(?:(\\\\[)((?>[^\\\\[\\\\]]+|\\\\[\\\\g<6>\\\\])*)(\\\\]))?                              # Optional default type\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.reference.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.variadic.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.assignment.php\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.section.array.begin.php\"\n                        },\n                        \"7\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parameter-default-types\"\n                                }\n                            ]\n                        },\n                        \"8\": {\n                            \"name\": \"punctuation.section.array.end.php\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\)|/[/*]|\\\\#)\",\n                    \"name\": \"meta.function.parameter.default.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-default-types\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"function-call\": {\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?xi)\\n(\\n  \\\\\\\\?(?<![a-z0-9_\\\\x{7f}-\\\\x{7fffffff}])                            # Optional root namespace\\n  [a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*          # First namespace\\n  (?:\\\\\\\\[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)+ # Additional namespaces\\n)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#namespace\"\n                                },\n                                {\n                                    \"match\":\n                                        \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                                    \"name\": \"entity.name.function.php\"\n                                }\n                            ]\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.arguments.begin.bracket.round.php\"\n                        }\n                    },\n                    \"end\": \"\\\\)|(?=\\\\?>)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.arguments.end.bracket.round.php\"\n                        }\n                    },\n                    \"name\": \"meta.function-call.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?i)(\\\\\\\\)?(?<![a-z0-9_\\\\x{7f}-\\\\x{7fffffff}])([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#namespace\"\n                                }\n                            ]\n                        },\n                        \"2\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#support\"\n                                },\n                                {\n                                    \"match\":\n                                        \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                                    \"name\": \"entity.name.function.php\"\n                                }\n                            ]\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arguments.begin.bracket.round.php\"\n                        }\n                    },\n                    \"end\": \"\\\\)|(?=\\\\?>)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.arguments.end.bracket.round.php\"\n                        }\n                    },\n                    \"name\": \"meta.function-call.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(?i)\\\\b(print|echo)\\\\b\",\n                    \"name\": \"support.function.construct.output.php\"\n                }\n            ]\n        },\n        \"heredoc\": {\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?i)(?=<<<\\\\s*(\\\"?)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)(\\\\1)\\\\s*$)\",\n                    \"end\": \"(?!\\\\G)\",\n                    \"name\": \"string.unquoted.heredoc.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc_interior\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?=<<<\\\\s*'([a-zA-Z_]+[a-zA-Z0-9_]*)'\\\\s*$)\",\n                    \"end\": \"(?!\\\\G)\",\n                    \"name\": \"string.unquoted.nowdoc.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#nowdoc_interior\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"heredoc_interior\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(HTML)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"text.html\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.html\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"text.html.basic\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(XML)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"text.xml\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.xml\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"text.xml\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(SQL)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.sql\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.sql\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"source.sql\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(JAVASCRIPT|JS)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.js\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.js\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"source.js\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(JSON)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.json\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.json\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"source.json\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(CSS)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.css\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"source.css\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*(\\\"?)(REGEXP?)(\\\\2)(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"string.regexp.heredoc.php\",\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"(\\\\\\\\){1,2}[.$^\\\\[\\\\]{}]\",\n                            \"name\": \"constant.character.escape.regex.php\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.arbitrary-repitition.php\"\n                                },\n                                \"3\": {\n                                    \"name\": \"punctuation.definition.arbitrary-repitition.php\"\n                                }\n                            },\n                            \"match\": \"({)\\\\d+(,\\\\d+)?(})\",\n                            \"name\": \"string.regexp.arbitrary-repitition.php\"\n                        },\n                        {\n                            \"begin\": \"\\\\[(?:\\\\^?\\\\])?\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.character-class.php\"\n                                }\n                            },\n                            \"end\": \"\\\\]\",\n                            \"name\": \"string.regexp.character-class.php\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\[\\\\\\\\'\\\\[\\\\]]\",\n                                    \"name\": \"constant.character.escape.php\"\n                                }\n                            ]\n                        },\n                        {\n                            \"match\": \"[$^+*]\",\n                            \"name\": \"keyword.operator.regexp.php\"\n                        },\n                        {\n                            \"begin\":\n                                \"(?i)(?<=^|\\\\s)(#)\\\\s(?=[[a-z0-9_\\\\x{7f}-\\\\x{7fffffff},. \\\\t?!-][^\\\\x{00}-\\\\x{7f}]]*$)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.comment.php\"\n                                }\n                            },\n                            \"end\": \"$\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.php\"\n                                }\n                            },\n                            \"name\": \"comment.line.number-sign.php\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?i)(<<<)\\\\s*(\\\"?)([a-z_\\\\x{7f}-\\\\x{7fffffff}]+[a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)(\\\\2)(\\\\s*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"end\": \"^(\\\\3)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"nowdoc_interior\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(<<<)\\\\s*'(HTML)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"text.html\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.html\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.basic\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*'(XML)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"text.xml\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.xml\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.xml\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*'(SQL)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.sql\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.sql\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.sql\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*'(JAVASCRIPT|JS)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.js\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.js\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.js\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*'(JSON)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.json\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.json\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.json\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*'(CSS)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"source.css\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.css\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.css\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*'(REGEXP?)'(\\\\s*)$\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"contentName\": \"string.regexp.nowdoc.php\",\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.php\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"(\\\\\\\\){1,2}[.$^\\\\[\\\\]{}]\",\n                            \"name\": \"constant.character.escape.regex.php\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.arbitrary-repitition.php\"\n                                },\n                                \"3\": {\n                                    \"name\": \"punctuation.definition.arbitrary-repitition.php\"\n                                }\n                            },\n                            \"match\": \"({)\\\\d+(,\\\\d+)?(})\",\n                            \"name\": \"string.regexp.arbitrary-repitition.php\"\n                        },\n                        {\n                            \"begin\": \"\\\\[(?:\\\\^?\\\\])?\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.character-class.php\"\n                                }\n                            },\n                            \"end\": \"\\\\]\",\n                            \"name\": \"string.regexp.character-class.php\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\[\\\\\\\\'\\\\[\\\\]]\",\n                                    \"name\": \"constant.character.escape.php\"\n                                }\n                            ]\n                        },\n                        {\n                            \"match\": \"[$^+*]\",\n                            \"name\": \"keyword.operator.regexp.php\"\n                        },\n                        {\n                            \"begin\":\n                                \"(?i)(?<=^|\\\\s)(#)\\\\s(?=[[a-z0-9_\\\\x{7f}-\\\\x{7fffffff},. \\\\t?!-][^\\\\x{00}-\\\\x{7f}]]*$)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.comment.php\"\n                                }\n                            },\n                            \"end\": \"$\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.php\"\n                                }\n                            },\n                            \"name\": \"comment.line.number-sign.php\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?i)(<<<)\\\\s*'([a-z_\\\\x{7f}-\\\\x{7fffffff}]+[a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)'(\\\\s*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"invalid.illegal.trailing-whitespace.php\"\n                        }\n                    },\n                    \"end\": \"^(\\\\2)(?=;?$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.nowdoc.php\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"instantiation\": {\n            \"begin\": \"(?i)(new)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.new.php\"\n                }\n            },\n            \"end\": \"(?i)(?=[^a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\])\",\n            \"patterns\": [\n                {\n                    \"match\": \"(?i)(parent|static|self)(?![a-z0-9_\\\\x{7f}-\\\\x{7fffffff}])\",\n                    \"name\": \"storage.type.php\"\n                },\n                {\n                    \"include\": \"#class-name\"\n                },\n                {\n                    \"include\": \"#variable-name\"\n                }\n            ]\n        },\n        \"interpolation\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\[0-7]{1,3}\",\n                    \"name\": \"constant.character.escape.octal.php\"\n                },\n                {\n                    \"match\": \"\\\\\\\\x[0-9A-Fa-f]{1,2}\",\n                    \"name\": \"constant.character.escape.hex.php\"\n                },\n                {\n                    \"match\": \"\\\\\\\\u{[0-9A-Fa-f]+}\",\n                    \"name\": \"constant.character.escape.unicode.php\"\n                },\n                {\n                    \"match\": \"\\\\\\\\[nrtvef$\\\\\\\\]\",\n                    \"name\": \"constant.character.escape.php\"\n                },\n                {\n                    \"begin\": \"{(?=\\\\$.*?})\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#variable-name\"\n                }\n            ]\n        },\n        \"interpolation_double_quoted\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\\\\"\",\n                    \"name\": \"constant.character.escape.php\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"invoke-call\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.php\"\n                },\n                \"2\": {\n                    \"name\": \"variable.other.php\"\n                }\n            },\n            \"match\":\n                \"(?i)(\\\\$+)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)(?=\\\\s*\\\\()\",\n            \"name\": \"meta.function-call.invoke.php\"\n        },\n        \"namespace\": {\n            \"begin\":\n                \"(?i)(?:(namespace)|[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?(\\\\\\\\)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"variable.language.namespace.php\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.separator.inheritance.php\"\n                }\n            },\n            \"end\": \"(?i)(?![a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\\\\\\\\)\",\n            \"name\": \"support.other.namespace.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\\",\n                    \"name\": \"punctuation.separator.inheritance.php\"\n                }\n            ]\n        },\n        \"numbers\": {\n            \"patterns\": [\n                {\n                    \"match\": \"0[xX][0-9a-fA-F]+\",\n                    \"name\": \"constant.numeric.hex.php\"\n                },\n                {\n                    \"match\": \"0[bB][01]+\",\n                    \"name\": \"constant.numeric.binary.php\"\n                },\n                {\n                    \"match\": \"0[0-7]+\",\n                    \"name\": \"constant.numeric.octal.php\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(?:\\n  [0-9]*(\\\\.)[0-9]+(?:[eE][+-]?[0-9]+)?|\\n  [0-9]+(\\\\.)[0-9]*(?:[eE][+-]?[0-9]+)?|\\n  [0-9]+[eE][+-]?[0-9]+\\n)\",\n                    \"name\": \"constant.numeric.decimal.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.decimal.period.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.decimal.period.php\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"0|[1-9][0-9]*\",\n                    \"name\": \"constant.numeric.decimal.php\"\n                }\n            ]\n        },\n        \"object\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(->)(\\\\$?{)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?i)(->)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arguments.begin.bracket.round.php\"\n                        }\n                    },\n                    \"end\": \"\\\\)|(?=\\\\?>)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.arguments.end.bracket.round.php\"\n                        }\n                    },\n                    \"name\": \"meta.method-call.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.property.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"match\":\n                        \"(?i)(->)((\\\\$+)?[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?\"\n                }\n            ]\n        },\n        \"parameter-default-types\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#strings\"\n                },\n                {\n                    \"include\": \"#numbers\"\n                },\n                {\n                    \"include\": \"#string-backtick\"\n                },\n                {\n                    \"include\": \"#variables\"\n                },\n                {\n                    \"match\": \"=>\",\n                    \"name\": \"keyword.operator.key.php\"\n                },\n                {\n                    \"match\": \"=\",\n                    \"name\": \"keyword.operator.assignment.php\"\n                },\n                {\n                    \"match\": \"&(?=\\\\s*\\\\$)\",\n                    \"name\": \"storage.modifier.reference.php\"\n                },\n                {\n                    \"begin\": \"(array)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.construct.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.array.begin.bracket.round.php\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.array.end.bracket.round.php\"\n                        }\n                    },\n                    \"name\": \"meta.array.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-default-types\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#instantiation\"\n                },\n                {\n                    \"begin\":\n                        \"(?xi)\\n(?=[a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]+(::)\\n  ([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?\\n)\",\n                    \"end\": \"(?i)(::)([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)?\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.other.class.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#class-name\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#constants\"\n                }\n            ]\n        },\n        \"php_doc\": {\n            \"patterns\": [\n                {\n                    \"match\": \"^(?!\\\\s*\\\\*).*?(?:(?=\\\\*\\\\/)|$\\\\n?)\",\n                    \"name\": \"invalid.illegal.missing-asterisk.phpdoc.php\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.phpdoc.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"invalid.illegal.wrong-access-type.phpdoc.php\"\n                        }\n                    },\n                    \"match\": \"^\\\\s*\\\\*\\\\s*(@access)\\\\s+((public|private|protected)|(.+))\\\\s*$\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.phpdoc.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"markup.underline.link.php\"\n                        }\n                    },\n                    \"match\": \"(@xlink)\\\\s+(.+)\\\\s*$\"\n                },\n                {\n                    \"begin\":\n                        \"(@(?:global|param|property(-(read|write))?|return|throws|var))\\\\s+(?=[A-Za-z_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]|\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.phpdoc.php\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/)\",\n                    \"contentName\": \"meta.other.type.phpdoc.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#php_doc_types_array_multiple\"\n                        },\n                        {\n                            \"include\": \"#php_doc_types_array_single\"\n                        },\n                        {\n                            \"include\": \"#php_doc_types\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n@\\n(\\n  api|abstract|author|category|copyright|example|global|inherit[Dd]oc|internal|\\n  license|link|method|property(-(read|write))?|package|param|return|see|since|source|\\n  static|subpackage|throws|todo|var|version|uses|deprecated|final|ignore\\n)\\\\b\",\n                    \"name\": \"keyword.other.phpdoc.php\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.phpdoc.php\"\n                        }\n                    },\n                    \"match\": \"{(@(link|inherit[Dd]oc)).+?}\",\n                    \"name\": \"meta.tag.inline.phpdoc.php\"\n                }\n            ]\n        },\n        \"php_doc_types\": {\n            \"match\":\n                \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]*(\\\\|[a-z_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]*)*\",\n            \"captures\": {\n                \"0\": {\n                    \"patterns\": [\n                        {\n                            \"match\":\n                                \"(?x)\\\\b\\n(string|integer|int|boolean|bool|float|double|object|mixed\\n|array|resource|void|null|callback|false|true|self)\\\\b\",\n                            \"name\": \"keyword.other.type.php\"\n                        },\n                        {\n                            \"include\": \"#class-name\"\n                        },\n                        {\n                            \"match\": \"\\\\|\",\n                            \"name\": \"punctuation.separator.delimiter.php\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"php_doc_types_array_multiple\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.type.begin.bracket.round.phpdoc.php\"\n                }\n            },\n            \"end\": \"(\\\\))(\\\\[\\\\])|(?=\\\\*/)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.type.end.bracket.round.phpdoc.php\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.array.phpdoc.php\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#php_doc_types_array_multiple\"\n                },\n                {\n                    \"include\": \"#php_doc_types_array_single\"\n                },\n                {\n                    \"include\": \"#php_doc_types\"\n                },\n                {\n                    \"match\": \"\\\\|\",\n                    \"name\": \"punctuation.separator.delimiter.php\"\n                }\n            ]\n        },\n        \"php_doc_types_array_single\": {\n            \"match\":\n                \"(?i)([a-z_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]*)(\\\\[\\\\])\",\n            \"captures\": {\n                \"1\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#php_doc_types\"\n                        }\n                    ]\n                },\n                \"2\": {\n                    \"name\": \"keyword.other.array.phpdoc.php\"\n                }\n            }\n        },\n        \"regex-double-quoted\": {\n            \"begin\": \"\\\"/(?=(\\\\\\\\.|[^\\\"/])++/[imsxeADSUXu]*\\\")\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"end\": \"(/)([imsxeADSUXu]*)(\\\")\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.regexp.double-quoted.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"(\\\\\\\\){1,2}[.$^\\\\[\\\\]{}]\",\n                    \"name\": \"constant.character.escape.regex.php\"\n                },\n                {\n                    \"include\": \"#interpolation_double_quoted\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.arbitrary-repetition.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arbitrary-repetition.php\"\n                        }\n                    },\n                    \"match\": \"({)\\\\d+(,\\\\d+)?(})\",\n                    \"name\": \"string.regexp.arbitrary-repetition.php\"\n                },\n                {\n                    \"begin\": \"\\\\[(?:\\\\^?\\\\])?\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.character-class.php\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"name\": \"string.regexp.character-class.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation_double_quoted\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"[$^+*]\",\n                    \"name\": \"keyword.operator.regexp.php\"\n                }\n            ]\n        },\n        \"regex-single-quoted\": {\n            \"begin\": \"'/(?=(\\\\\\\\(?:\\\\\\\\(?:\\\\\\\\[\\\\\\\\']?|[^'])|.)|[^'/])++/[imsxeADSUXu]*')\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"end\": \"(/)([imsxeADSUXu]*)(')\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.regexp.single-quoted.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#single_quote_regex_escape\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.arbitrary-repetition.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arbitrary-repetition.php\"\n                        }\n                    },\n                    \"match\": \"({)\\\\d+(,\\\\d+)?(})\",\n                    \"name\": \"string.regexp.arbitrary-repetition.php\"\n                },\n                {\n                    \"begin\": \"\\\\[(?:\\\\^?\\\\])?\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.character-class.php\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"name\": \"string.regexp.character-class.php\"\n                },\n                {\n                    \"match\": \"[$^+*]\",\n                    \"name\": \"keyword.operator.regexp.php\"\n                }\n            ]\n        },\n        \"scope-resolution\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"([A-Za-z_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\][A-Za-z0-9_\\\\x{7f}-\\\\x{7fffffff}\\\\\\\\]*)(?=\\\\s*::)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\b(self|static|parent)\\\\b\",\n                                    \"name\": \"storage.type.php\"\n                                },\n                                {\n                                    \"include\": \"#class-name\"\n                                },\n                                {\n                                    \"include\": \"#variable-name\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\":\n                        \"(?i)(::)\\\\s*([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arguments.begin.bracket.round.php\"\n                        }\n                    },\n                    \"end\": \"\\\\)|(?=\\\\?>)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.arguments.end.bracket.round.php\"\n                        }\n                    },\n                    \"name\": \"meta.method-call.static.php\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(?i)(::)\\\\s*(class)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.class.php\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\n(::)\\\\s*\\n(?:\\n  ((\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*) # Variable\\n  |\\n  ([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)       # Constant\\n)?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.class.php\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"constant.other.class.php\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"single_quote_regex_escape\": {\n            \"match\": \"\\\\\\\\(?:\\\\\\\\(?:\\\\\\\\[\\\\\\\\']?|[^'])|.)\",\n            \"name\": \"constant.character.escape.php\"\n        },\n        \"sql-string-double-quoted\": {\n            \"begin\": \"\\\"\\\\s*(?=(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|AND)\\\\b)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"contentName\": \"source.sql.embedded.php\",\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.quoted.double.sql.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"(#)(\\\\\\\\\\\"|[^\\\"])*(?=\\\"|$)\",\n                    \"name\": \"comment.line.number-sign.sql\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.sql\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(--)(\\\\\\\\\\\"|[^\\\"])*(?=\\\"|$)\",\n                    \"name\": \"comment.line.double-dash.sql\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.sql\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"\\\\\\\\[\\\\\\\\\\\"`']\",\n                    \"name\": \"constant.character.escape.php\"\n                },\n                {\n                    \"match\": \"'(?=((\\\\\\\\')|[^'\\\"])*(\\\"|$))\",\n                    \"name\": \"string.quoted.single.unclosed.sql\"\n                },\n                {\n                    \"match\": \"`(?=((\\\\\\\\`)|[^`\\\"])*(\\\"|$))\",\n                    \"name\": \"string.quoted.other.backtick.unclosed.sql\"\n                },\n                {\n                    \"begin\": \"'\",\n                    \"end\": \"'\",\n                    \"name\": \"string.quoted.single.sql\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation_double_quoted\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"`\",\n                    \"end\": \"`\",\n                    \"name\": \"string.quoted.other.backtick.sql\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation_double_quoted\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#interpolation_double_quoted\"\n                },\n                {\n                    \"include\": \"source.sql\"\n                }\n            ]\n        },\n        \"sql-string-single-quoted\": {\n            \"begin\": \"'\\\\s*(?=(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|AND)\\\\b)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"contentName\": \"source.sql.embedded.php\",\n            \"end\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.quoted.single.sql.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"(#)(\\\\\\\\'|[^'])*(?='|$)\",\n                    \"name\": \"comment.line.number-sign.sql\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.sql\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(--)(\\\\\\\\'|[^'])*(?='|$)\",\n                    \"name\": \"comment.line.double-dash.sql\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.sql\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"\\\\\\\\[\\\\\\\\'`\\\"]\",\n                    \"name\": \"constant.character.escape.php\"\n                },\n                {\n                    \"match\": \"`(?=((\\\\\\\\`)|[^`'])*('|$))\",\n                    \"name\": \"string.quoted.other.backtick.unclosed.sql\"\n                },\n                {\n                    \"match\": \"\\\"(?=((\\\\\\\\\\\")|[^\\\"'])*('|$))\",\n                    \"name\": \"string.quoted.double.unclosed.sql\"\n                },\n                {\n                    \"include\": \"source.sql\"\n                }\n            ]\n        },\n        \"string-backtick\": {\n            \"begin\": \"`\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.interpolated.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\`\",\n                    \"name\": \"constant.character.escape.php\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"string-double-quoted\": {\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.quoted.double.php\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolation_double_quoted\"\n                }\n            ]\n        },\n        \"string-single-quoted\": {\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.php\"\n                }\n            },\n            \"end\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.php\"\n                }\n            },\n            \"name\": \"string.quoted.single.php\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\[\\\\\\\\']\",\n                    \"name\": \"constant.character.escape.php\"\n                }\n            ]\n        },\n        \"strings\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regex-double-quoted\"\n                },\n                {\n                    \"include\": \"#sql-string-double-quoted\"\n                },\n                {\n                    \"include\": \"#string-double-quoted\"\n                },\n                {\n                    \"include\": \"#regex-single-quoted\"\n                },\n                {\n                    \"include\": \"#sql-string-single-quoted\"\n                },\n                {\n                    \"include\": \"#string-single-quoted\"\n                }\n            ]\n        },\n        \"support\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?xi)\\n\\\\b\\napc_(\\n  store|sma_info|compile_file|clear_cache|cas|cache_info|inc|dec|define_constants|delete(_file)?|\\n  exists|fetch|load_constants|add|bin_(dump|load)(file)?\\n)\\\\b\",\n                    \"name\": \"support.function.apc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  shuffle|sizeof|sort|next|nat(case)?sort|count|compact|current|in_array|usort|uksort|uasort|\\n  pos|prev|end|each|extract|ksort|key(_exists)?|krsort|list|asort|arsort|rsort|reset|range|\\n  array(_(shift|sum|splice|search|slice|chunk|change_key_case|count_values|column|combine|\\n          (diff|intersect)(_(u)?(key|assoc))?|u(diff|intersect)(_(u)?assoc)?|unshift|unique|\\n          pop|push|pad|product|values|keys|key_exists|filter|fill(_keys)?|flip|walk(_recursive)?|\\n          reduce|replace(_recursive)?|reverse|rand|multisort|merge(_recursive)?|map)?)\\n)\\\\b\",\n                    \"name\": \"support.function.array.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  show_source|sys_getloadavg|sleep|highlight_(file|string)|constant|connection_(aborted|status)|\\n  time_(nanosleep|sleep_until)|ignore_user_abort|die|define(d)?|usleep|uniqid|unpack|__halt_compiler|\\n  php_(check_syntax|strip_whitespace)|pack|eval|exit|get_browser\\n)\\\\b\",\n                    \"name\": \"support.function.basic_functions.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bbc(scale|sub|sqrt|comp|div|pow(mod)?|add|mod|mul)\\\\b\",\n                    \"name\": \"support.function.bcmath.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bblenc_encrypt\\\\b\",\n                    \"name\": \"support.function.blenc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bbz(compress|close|open|decompress|errstr|errno|error|flush|write|read)\\\\b\",\n                    \"name\": \"support.function.bz2.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  (French|Gregorian|Jewish|Julian)ToJD|cal_(to_jd|info|days_in_month|from_jd)|unixtojd|\\n  jdto(unix|jewish)|easter_(date|days)|JD(MonthName|To(Gregorian|Julian|French)|DayOfWeek)\\n)\\\\b\",\n                    \"name\": \"support.function.calendar.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  class_alias|all_user_method(_array)?|is_(a|subclass_of)|__autoload|(class|interface|method|property|trait)_exists|\\n  get_(class(_(vars|methods))?|(called|parent)_class|object_vars|declared_(classes|interfaces|traits))\\n)\\\\b\",\n                    \"name\": \"support.function.classobj.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  com_(create_guid|print_typeinfo|event_sink|load_typelib|get_active_object|message_pump)|\\n  variant_(sub|set(_type)?|not|neg|cast|cat|cmp|int|idiv|imp|or|div|date_(from|to)_timestamp|\\n           pow|eqv|fix|and|add|abs|round|get_type|xor|mod|mul)\\n)\\\\b\",\n                    \"name\": \"support.function.com.php\"\n                },\n                {\n                    \"begin\": \"(?i)\\\\b(isset|unset|eval|empty|list)\\\\b\",\n                    \"name\": \"support.function.construct.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\b(print|echo)\\\\b\",\n                    \"name\": \"support.function.construct.output.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bctype_(space|cntrl|digit|upper|punct|print|lower|alnum|alpha|graph|xdigit)\\\\b\",\n                    \"name\": \"support.function.ctype.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\ncurl_(\\n  share_(close|init|setopt)|strerror|setopt(_array)?|copy_handle|close|init|unescape|pause|escape|\\n  errno|error|exec|version|file_create|reset|getinfo|\\n  multi_(strerror|setopt|select|close|init|info_read|(add|remove)_handle|getcontent|exec)\\n)\\\\b\",\n                    \"name\": \"support.function.curl.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  strtotime|str[fp]time|checkdate|time|timezone_name_(from_abbr|get)|idate|\\n  timezone_((location|offset|transitions|version)_get|(abbreviations|identifiers)_list|open)|\\n  date(_(sun(rise|set)|sun_info|sub|create(_(immutable_)?from_format)?|timestamp_(get|set)|timezone_(get|set)|time_set|\\n         isodate_set|interval_(create_from_date_string|format)|offset_get|diff|default_timezone_(get|set)|date_set|\\n         parse(_from_format)?|format|add|get_last_errors|modify))?|\\n  localtime|get(date|timeofday)|gm(strftime|date|mktime)|microtime|mktime\\n)\\\\b\",\n                    \"name\": \"support.function.datetime.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bdba_(sync|handlers|nextkey|close|insert|optimize|open|delete|popen|exists|key_split|firstkey|fetch|list|replace)\\\\b\",\n                    \"name\": \"support.function.dba.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bdbx_(sort|connect|compare|close|escape_string|error|query|fetch_row)\\\\b\",\n                    \"name\": \"support.function.dbx.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(scandir|chdir|chroot|closedir|opendir|dir|rewinddir|readdir|getcwd)\\\\b\",\n                    \"name\": \"support.function.dir.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\neio_(\\n  sync(fs)?|sync_file_range|symlink|stat(vfs)?|sendfile|set_min_parallel|set_max_(idle|poll_(reqs|time)|parallel)|\\n  seek|n(threads|op|pending|reqs|ready)|chown|chmod|custom|close|cancel|truncate|init|open|dup2|unlink|utime|poll|\\n  event_loop|f(sync|stat(vfs)?|chown|chmod|truncate|datasync|utime|allocate)|write|lstat|link|rename|realpath|\\n  read(ahead|dir|link)?|rmdir|get_(event_stream|last_error)|grp(_(add|cancel|limit))?|mknod|mkdir|busy\\n)\\\\b\",\n                    \"name\": \"support.function.eio.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nenchant_(\\n  dict_(store_replacement|suggest|check|is_in_session|describe|quick_check|add_to_(personal|session)|get_error)|\\n  broker_(set_ordering|init|dict_exists|describe|free(_dict)?|list_dicts|request_(pwl_)?dict|get_error)\\n)\\\\b\",\n                    \"name\": \"support.function.enchant.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bsplit(i)?|sql_regcase|ereg(i)?(_replace)?\\\\b\",\n                    \"name\": \"support.function.ereg.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b((restore|set)_(error_handler|exception_handler)|trigger_error|debug_(print_)?backtrace|user_error|error_(log|reporting|get_last))\\\\b\",\n                    \"name\": \"support.function.errorfunc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bshell_exec|system|passthru|proc_(nice|close|terminate|open|get_status)|escapeshell(arg|cmd)|exec\\\\b\",\n                    \"name\": \"support.function.exec.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(exif_(thumbnail|tagname|imagetype|read_data)|read_exif_data)\\\\b\",\n                    \"name\": \"support.function.exif.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nfann_(\\n  (duplicate|length|merge|shuffle|subset)_train_data|scale_(train(_data)?|(input|output)(_train_data)?)|\\n  set_(scaling_params|sarprop_(step_error_(shift|threshold_factor)|temperature|weight_decay_shift)|\\n       cascade_(num_candidate_groups|candidate_(change_fraction|limit|stagnation_epochs)|\\n                output_(change_fraction|stagnation_epochs)|weight_multiplier|activation_(functions|steepnesses)|\\n                (max|min)_(cand|out)_epochs)|\\n       callback|training_algorithm|train_(error|stop)_function|(input|output)_scaling_params|error_log|\\n       quickprop_(decay|mu)|weight(_array)?|learning_(momentum|rate)|bit_fail_limit|\\n       activation_(function|steepness)(_(hidden|layer|output))?|\\n       rprop_((decrease|increase)_factor|delta_(max|min|zero)))|\\n  save(_train)?|num_(input|output)_train_data|copy|clear_scaling_params|cascadetrain_on_(file|data)|\\n  create_((sparse|shortcut|standard)(_array)?|train(_from_callback)?|from_file)|\\n  test(_data)?|train(_(on_(file|data)|epoch))?|init_weights|descale_(input|output|train)|destroy(_train)?|\\n  print_error|run|reset_(MSE|err(no|str))|read_train_from_file|randomize_weights|\\n  get_(sarprop_(step_error_(shift|threshold_factor)|temperature|weight_decay_shift)|num_(input|output|layers)|\\n       network_type|MSE|connection_(array|rate)|bias_array|bit_fail(_limit)?|\\n       cascade_(num_(candidates|candidate_groups)|(candidate|output)_(change_fraction|limit|stagnation_epochs)|\\n                weight_multiplier|activation_(functions|steepnesses)(_count)?|(max|min)_(cand|out)_epochs)|\\n       total_(connections|neurons)|training_algorithm|train_(error|stop)_function|err(no|str)|\\n       quickprop_(decay|mu)|learning_(momentum|rate)|layer_array|activation_(function|steepness)|\\n       rprop_((decrease|increase)_factor|delta_(max|min|zero)))\\n)\\\\b\",\n                    \"name\": \"support.function.fann.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  symlink|stat|set_file_buffer|chown|chgrp|chmod|copy|clearstatcache|touch|tempnam|tmpfile|\\n  is_(dir|(uploaded_)?file|executable|link|readable|writ(e)?able)|disk_(free|total)_space|diskfreespace|\\n  dirname|delete|unlink|umask|pclose|popen|pathinfo|parse_ini_(file|string)|fscanf|fstat|fseek|fnmatch|\\n  fclose|ftell|ftruncate|file(size|[acm]time|type|inode|owner|perms|group)?|file_(exists|(get|put)_contents)|\\n  f(open|puts|putcsv|passthru|eof|flush|write|lock|read|gets(s)?|getc(sv)?)|lstat|lchown|lchgrp|link(info)?|\\n  rename|rewind|read(file|link)|realpath(_cache_(get|size))?|rmdir|glob|move_uploaded_file|mkdir|basename\\n)\\\\b\",\n                    \"name\": \"support.function.file.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(finfo_(set_flags|close|open|file|buffer)|mime_content_type)\\\\b\",\n                    \"name\": \"support.function.fileinfo.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bfilter_(has_var|input(_array)?|id|var(_array)?|list)\\\\b\",\n                    \"name\": \"support.function.filter.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bfastcgi_finish_request\\\\b\",\n                    \"name\": \"support.function.fpm.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(call_user_(func|method)(_array)?|create_function|unregister_tick_function|forward_static_call(_array)?|function_exists|func_(num_args|get_arg(s)?)|register_(shutdown|tick)_function|get_defined_functions)\\\\b\",\n                    \"name\": \"support.function.funchand.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b((n)?gettext|textdomain|d((n)?gettext|c(n)?gettext)|bind(textdomain|_textdomain_codeset))\\\\b\",\n                    \"name\": \"support.function.gettext.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\ngmp_(\\n  scan[01]|strval|sign|sub|setbit|sqrt(rem)?|hamdist|neg|nextprime|com|clrbit|cmp|testbit|\\n  intval|init|invert|import|or|div(exact)?|div_(q|qr|r)|jacobi|popcount|pow(m)?|perfect_square|\\n  prob_prime|export|fact|legendre|and|add|abs|root(rem)?|random(_(bits|range))?|gcd(ext)?|xor|mod|mul\\n)\\\\b\",\n                    \"name\": \"support.function.gmp.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bhash(_(hmac(_file)?|copy|init|update(_(file|stream))?|pbkdf2|equals|file|final|algos))?\\\\b\",\n                    \"name\": \"support.function.hash.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  http_(support|send_(status|stream|content_(disposition|type)|data|file|last_modified)|head|\\n        negotiate_(charset|content_type|language)|chunked_decode|cache_(etag|last_modified)|throttle|\\n        inflate|deflate|date|post_(data|fields)|put_(data|file|stream)|persistent_handles_(count|clean|ident)|\\n        parse_(cookie|headers|message|params)|redirect|request(_(method_(exists|name|(un)?register)|body_encode))?|\\n        get(_request_(headers|body(_stream)?))?|match_(etag|modified|request_header)|build_(cookie|str|url))|\\n  ob_(etag|deflate|inflate)handler\\n)\\\\b\",\n                    \"name\": \"support.function.http.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(iconv(_(str(pos|len|rpos)|substr|(get|set)_encoding|mime_(decode(_headers)?|encode)))?|ob_iconv_handler)\\\\b\",\n                    \"name\": \"support.function.iconv.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\biis_((start|stop)_(service|server)|set_(script_map|server_rights|dir_security|app_settings)|(add|remove)_server|get_(script_map|service_state|server_(rights|by_(comment|path))|dir_security))\\\\b\",\n                    \"name\": \"support.function.iisfunc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  iptc(embed|parse)|(jpeg|png)2wbmp|gd_info|getimagesize(fromstring)?|\\n  image(s[xy]|scale|(char|string)(up)?|set(style|thickness|tile|interpolation|pixel|brush)|savealpha|\\n        convolution|copy(resampled|resized|merge(gray)?)?|colors(forindex|total)|\\n        color(set|closest(alpha|hwb)?|transparent|deallocate|(allocate|exact|resolve)(alpha)?|at|match)|\\n        crop(auto)?|create(truecolor|from(string|jpeg|png|wbmp|webp|gif|gd(2(part)?)?|xpm|xbm))?|\\n        types|ttf(bbox|text)|truecolortopalette|istruecolor|interlace|2wbmp|destroy|dashedline|jpeg|\\n        _type_to_(extension|mime_type)|ps(slantfont|text|(encode|extend|free|load)font|bbox)|png|polygon|\\n        palette(copy|totruecolor)|ellipse|ft(text|bbox)|filter|fill|filltoborder|\\n        filled(arc|ellipse|polygon|rectangle)|font(height|width)|flip|webp|wbmp|line|loadfont|layereffect|\\n        antialias|affine(matrix(concat|get))?|alphablending|arc|rotate|rectangle|gif|gd(2)?|gammacorrect|\\n        grab(screen|window)|xbm)\\n)\\\\b\",\n                    \"name\": \"support.function.image.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  sys_get_temp_dir|set_(time_limit|include_path|magic_quotes_runtime)|cli_(get|set)_process_title|\\n  ini_(alter|get(_all)?|restore|set)|zend_(thread_id|version|logo_guid)|dl|php(credits|info|version)|\\n  php_(sapi_name|ini_(scanned_files|loaded_file)|uname|logo_guid)|putenv|extension_loaded|version_compare|\\n  assert(_options)?|restore_include_path|gc_(collect_cycles|disable|enable(d)?)|getopt|\\n  get_(cfg_var|current_user|defined_constants|extension_funcs|include_path|included_files|loaded_extensions|\\n       magic_quotes_(gpc|runtime)|required_files|resources)|\\n  get(env|lastmod|rusage|my(inode|[gup]id))|\\n  memory_get_(peak_)?usage|main|magic_quotes_runtime\\n)\\\\b\",\n                    \"name\": \"support.function.info.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nibase_(\\n  set_event_handler|service_(attach|detach)|server_info|num_(fields|params)|name_result|connect|\\n  commit(_ret)?|close|trans|delete_user|drop_db|db_info|pconnect|param_info|prepare|err(code|msg)|\\n  execute|query|field_info|fetch_(assoc|object|row)|free_(event_handler|query|result)|wait_event|\\n  add_user|affected_rows|rollback(_ret)?|restore|gen_id|modify_user|maintain_db|backup|\\n  blob_(cancel|close|create|import|info|open|echo|add|get)\\n)\\\\b\",\n                    \"name\": \"support.function.interbase.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  normalizer_(normalize|is_normalized)|idn_to_(unicode|utf8|ascii)|\\n  numfmt_(set_(symbol|(text_)?attribute|pattern)|create|(parse|format)(_currency)?|\\n          get_(symbol|(text_)?attribute|pattern|error_(code|message)|locale))|\\n  collator_(sort(_with_sort_keys)?|set_(attribute|strength)|compare|create|asort|\\n            get_(strength|sort_key|error_(code|message)|locale|attribute))|\\n  transliterator_(create(_(inverse|from_rules))?|transliterate|list_ids|get_error_(code|message))|\\n  intl(cal|tz)_get_error_(code|message)|intl_(is_failure|error_name|get_error_(code|message))|\\n  datefmt_(set_(calendar|lenient|pattern|timezone(_id)?)|create|is_lenient|parse|format(_object)?|localtime|\\n           get_(calendar(_object)?|time(type|zone(_id)?)|datetype|pattern|error_(code|message)|locale))|\\n  locale_(set_default|compose|canonicalize|parse|filter_matches|lookup|accept_from_http|\\n          get_(script|display_(script|name|variant|language|region)|default|primary_language|keywords|all_variants|region))|\\n  resourcebundle_(create|count|locales|get(_(error_(code|message)))?)|\\n  grapheme_(str(i?str|r?i?pos|len)|substr|extract)|\\n  msgfmt_(set_pattern|create|(format|parse)(_message)?|get_(pattern|error_(code|message)|locale))\\n)\\\\b\",\n                    \"name\": \"support.function.intl.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bjson_(decode|encode|last_error(_msg)?)\\\\b\",\n                    \"name\": \"support.function.json.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nldap_(\\n  start|tls|sort|search|sasl_bind|set_(option|rebind_proc)|(first|next)_(attribute|entry|reference)|\\n  connect|control_paged_result(_response)?|count_entries|compare|close|t61_to_8859|8859_to_t61|\\n  dn2ufn|delete|unbind|parse_(reference|result)|escape|errno|err2str|error|explode_dn|bind|\\n  free_result|list|add|rename|read|get_(option|dn|entries|values(_len)?|attributes)|modify(_batch)?|\\n  mod_(add|del|replace)\\n)\\\\b\",\n                    \"name\": \"support.function.ldap.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\blibxml_(set_(streams_context|external_entity_loader)|clear_errors|disable_entity_loader|use_internal_errors|get_(errors|last_error))\\\\b\",\n                    \"name\": \"support.function.libxml.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\b(ezmlm_hash|mail)\\\\b\",\n                    \"name\": \"support.function.mail.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  (a)?(cos|sin|tan)(h)?|sqrt|srand|hypot|hexdec|ceil|is_(nan|(in)?finite)|octdec|dec(hex|oct|bin)|deg2rad|\\n  pi|pow|exp(m1)?|floor|fmod|lcg_value|log(1(p|0))?|atan2|abs|round|rand|rad2deg|getrandmax|\\n  mt_(srand|rand|getrandmax)|max|min|bindec|base_convert\\n)\\\\b\",\n                    \"name\": \"support.function.math.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nmb_(\\n  str(cut|str|to(lower|upper)|istr|ipos|imwidth|pos|width|len|rchr|richr|ripos|rpos)|\\n  substitute_character|substr(_count)?|split|send_mail|http_(input|output)|check_encoding|\\n  convert_(case|encoding|kana|variables)|internal_encoding|output_handler|decode_(numericentity|mimeheader)|\\n  detect_(encoding|order)|parse_str|preferred_mime_name|encoding_aliases|encode_(numericentity|mimeheader)|\\n  ereg(i(_replace)?)?|ereg_(search(_(get(pos|regs)|init|regs|(set)?pos))?|replace(_callback)?|match)|\\n  list_encodings|language|regex_(set_options|encoding)|get_info\\n)\\\\b\",\n                    \"name\": \"support.function.mbstring.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  mcrypt_(\\n    cfb|create_iv|cbc|ofb|decrypt|encrypt|ecb|list_(algorithms|modes)|generic(_((de)?init|end))?|\\n    enc_(self_test|is_block_(algorithm|algorithm_mode|mode)|\\n    get_(supported_key_sizes|(block|iv|key)_size|(algorithms|modes)_name))|\\n    get_(cipher_name|(block|iv|key)_size)|\\n    module_(close|self_test|is_block_(algorithm|algorithm_mode|mode)|open|\\n            get_(supported_key_sizes|algo_(block|key)_size)))|\\n  mdecrypt_generic\\n)\\\\b\",\n                    \"name\": \"support.function.mcrypt.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bmemcache_debug\\\\b\",\n                    \"name\": \"support.function.memcache.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bmhash(_(count|keygen_s2k|get_(hash_name|block_size)))?\\\\b\",\n                    \"name\": \"support.function.mhash.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(log_(cmd_(insert|delete|update)|killcursor|write_batch|reply|getmore)|bson_(decode|encode))\\\\b\",\n                    \"name\": \"support.function.mongo.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nmysql_(\\n  stat|set_charset|select_db|num_(fields|rows)|connect|client_encoding|close|create_db|escape_string|\\n  thread_id|tablename|insert_id|info|data_seek|drop_db|db_(name|query)|unbuffered_query|pconnect|ping|\\n  errno|error|query|field_(seek|name|type|table|flags|len)|fetch_(object|field|lengths|assoc|array|row)|\\n  free_result|list_(tables|dbs|processes|fields)|affected_rows|result|real_escape_string|\\n  get_(client|host|proto|server)_info\\n)\\\\b\",\n                    \"name\": \"support.function.mysql.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nmysqli_(\\n  ssl_set|store_result|stat|send_(query|long_data)|set_(charset|opt|local_infile_(default|handler))|\\n  stmt_(store_result|send_long_data|next_result|close|init|data_seek|prepare|execute|fetch|free_result|\\n        attr_(get|set)|result_metadata|reset|get_(result|warnings)|more_results|bind_(param|result))|\\n  select_db|slave_query|savepoint|next_result|change_user|character_set_name|connect|commit|\\n  client_encoding|close|thread_safe|init|options|(enable|disable)_(reads_from_master|rpl_parse)|\\n  dump_debug_info|debug|data_seek|use_result|ping|poll|param_count|prepare|escape_string|execute|\\n  embedded_server_(start|end)|kill|query|field_seek|free_result|autocommit|rollback|report|refresh|\\n  fetch(_(object|fields|field(_direct)?|assoc|all|array|row))?|rpl_(parse_enabled|probe|query_type)|\\n  release_savepoint|reap_async_query|real_(connect|escape_string|query)|more_results|multi_query|\\n  get_(charset|connection_stats|client_(stats|info|version)|cache_stats|warnings|links_stats|metadata)|\\n  master_query|bind_(param|result)|begin_transaction\\n)\\\\b\",\n                    \"name\": \"support.function.mysqli.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bmysqlnd_memcache_(set|get_config)\\\\b\",\n                    \"name\": \"support.function.mysqlnd-memcache.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bmysqlnd_ms_(set_(user_pick_server|qos)|dump_servers|query_is_select|fabric_select_(shard|global)|get_(stats|last_(used_connection|gtid))|xa_(commit|rollback|gc|begin)|match_wild)\\\\b\",\n                    \"name\": \"support.function.mysqlnd-ms.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bmysqlnd_qc_(set_(storage_handler|cache_condition|is_select|user_handlers)|clear_cache|get_(normalized_query_trace_log|core_stats|cache_info|query_trace_log|available_handlers))\\\\b\",\n                    \"name\": \"support.function.mysqlnd-qc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bmysqlnd_uh_(set_(statement|connection)_proxy|convert_to_mysqlnd)\\\\b\",\n                    \"name\": \"support.function.mysqlnd-uh.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  syslog|socket_(set_(blocking|timeout)|get_status)|set(raw)?cookie|http_response_code|openlog|\\n  headers_(list|sent)|header(_(register_callback|remove))?|checkdnsrr|closelog|inet_(ntop|pton)|ip2long|\\n  openlog|dns_(check_record|get_(record|mx))|define_syslog_variables|(p)?fsockopen|long2ip|\\n  get(servby(name|port)|host(name|by(name(l)?|addr))|protoby(name|number)|mxrr)\\n)\\\\b\",\n                    \"name\": \"support.function.network.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bnsapi_(virtual|response_headers|request_headers)\\\\b\",\n                    \"name\": \"support.function.nsapi.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  oci(statementtype|setprefetch|serverversion|savelob(file)?|numcols|new(collection|cursor|descriptor)|nlogon|\\n      column(scale|size|name|type(raw)?|isnull|precision)|coll(size|trim|assign(elem)?|append|getelem|max)|commit|\\n      closelob|cancel|internaldebug|definebyname|plogon|parse|error|execute|fetch(statement|into)?|\\n      free(statement|collection|cursor|desc)|write(temporarylob|lobtofile)|loadlob|log(on|off)|rowcount|rollback|\\n      result|bindbyname)|\\n  oci_(statement_type|set_(client_(info|identifier)|prefetch|edition|action|module_name)|server_version|\\n       num_(fields|rows)|new_(connect|collection|cursor|descriptor)|connect|commit|client_version|close|cancel|\\n       internal_debug|define_by_name|pconnect|password_change|parse|error|execute|bind_(array_)?by_name|\\n       field_(scale|size|name|type(_raw)?|is_null|precision)|fetch(_(object|assoc|all|array|row))?|\\n       free_(statement|descriptor)|lob_(copy|is_equal)|rollback|result|get_implicit_resultset)\\n)\\\\b\",\n                    \"name\": \"support.function.oci8.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bopcache_(compile_file|invalidate|reset|get_(status|configuration))\\\\b\",\n                    \"name\": \"support.function.opcache.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nopenssl_(\\n  sign|spki_(new|export(_challenge)?|verify)|seal|csr_(sign|new|export(_to_file)?|get_(subject|public_key))|\\n  cipher_iv_length|open|dh_compute_key|digest|decrypt|public_(decrypt|encrypt)|encrypt|error_string|\\n  pkcs12_(export(_to_file)?|read)|pkcs7_(sign|decrypt|encrypt|verify)|verify|free_key|random_pseudo_bytes|\\n  pkey_(new|export(_to_file)?|free|get_(details|public|private))|private_(decrypt|encrypt)|pbkdf2|\\n  get_((cipher|md)_methods|cert_locations|(public|private)key)|\\n  x509_(check_private_key|checkpurpose|parse|export(_to_file)?|fingerprint|free|read)\\n)\\\\b\",\n                    \"name\": \"support.function.openssl.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  output_(add_rewrite_var|reset_rewrite_vars)|flush|\\n  ob_(start|clean|implicit_flush|end_(clean|flush)|flush|list_handlers|gzhandler|\\n      get_(status|contents|clean|flush|length|level))\\n)\\\\b\",\n                    \"name\": \"support.function.output.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bpassword_(hash|needs_rehash|verify|get_info)\\\\b\",\n                    \"name\": \"support.function.password.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\npcntl_(\\n  strerror|signal(_dispatch)?|sig(timedwait|procmask|waitinfo)|setpriority|errno|exec|fork|\\n  w(stopsig|termsig|if(stopped|signaled|exited))|wait(pid)?|alarm|getpriority|get_last_error\\n)\\\\b\",\n                    \"name\": \"support.function.pcntl.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\npg_(\\n  socket|send_(prepare|execute|query(_params)?)|set_(client_encoding|error_verbosity)|select|host|\\n  num_(fields|rows)|consume_input|connection_(status|reset|busy)|connect(_poll)?|convert|copy_(from|to)|\\n  client_encoding|close|cancel_query|tty|transaction_status|trace|insert|options|delete|dbname|untrace|\\n  unescape_bytea|update|pconnect|ping|port|put_line|parameter_status|prepare|version|query(_params)?|\\n  escape_(string|identifier|literal|bytea)|end_copy|execute|flush|free_result|last_(notice|error|oid)|\\n  field_(size|num|name|type(_oid)?|table|is_null|prtlen)|affected_rows|result_(status|seek|error(_field)?)|\\n  fetch_(object|assoc|all(_columns)?|array|row|result)|get_(notify|pid|result)|meta_data|\\n  lo_(seek|close|create|tell|truncate|import|open|unlink|export|write|read(_all)?)|\\n)\\\\b\",\n                    \"name\": \"support.function.pgsql.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(virtual|getallheaders|apache_((get|set)env|note|child_terminate|lookup_uri|response_headers|reset_timeout|request_headers|get_(version|modules)))\\\\b\",\n                    \"name\": \"support.function.php_apache.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bdom_import_simplexml\\\\b\",\n                    \"name\": \"support.function.php_dom.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nftp_(\\n  ssl_connect|systype|site|size|set_option|nlist|nb_(continue|f?(put|get))|ch(dir|mod)|connect|cdup|close|\\n  delete|put|pwd|pasv|exec|quit|f(put|get)|login|alloc|rename|raw(list)?|rmdir|get(_option)?|mdtm|mkdir\\n)\\\\b\",\n                    \"name\": \"support.function.php_ftp.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nimap_(\\n  (create|delete|list|rename|scan)(mailbox)?|status|sort|subscribe|set_quota|set(flag_full|acl)|search|savebody|\\n  num_(recent|msg)|check|close|clearflag_full|thread|timeout|open|header(info)?|headers|append|alerts|reopen|\\n  8bit|unsubscribe|undelete|utf7_(decode|encode)|utf8|uid|ping|errors|expunge|qprint|gc|\\n  fetch(structure|header|text|mime|body)|fetch_overview|lsub|list(scan|subscribed)|last_error|\\n  rfc822_(parse_(headers|adrlist)|write_address)|get(subscribed|acl|mailboxes)|get_quota(root)?|\\n  msgno|mime_header_decode|mail_(copy|compose|move)|mail|mailboxmsginfo|binary|body(struct)?|base64\\n)\\\\b\",\n                    \"name\": \"support.function.php_imap.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nmssql_(\\n  select_db|num_(fields|rows)|next_result|connect|close|init|data_seek|pconnect|execute|query|\\n  field_(seek|name|type|length)|fetch_(object|field|assoc|array|row|batch)|free_(statement|result)|\\n  rows_affected|result|guid_string|get_last_message|min_(error|message)_severity|bind\\n)\\\\b\",\n                    \"name\": \"support.function.php_mssql.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nodbc_(\\n  statistics|specialcolumns|setoption|num_(fields|rows)|next_result|connect|columns|columnprivileges|commit|\\n  cursor|close(_all)?|tables|tableprivileges|do|data_source|pconnect|primarykeys|procedures|procedurecolumns|\\n  prepare|error(msg)?|exec(ute)?|field_(scale|num|name|type|precision|len)|foreignkeys|free_result|\\n  fetch_(into|object|array|row)|longreadlen|autocommit|rollback|result(_all)?|gettypeinfo|binmode\\n)\\\\b\",\n                    \"name\": \"support.function.php_odbc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bpreg_(split|quote|filter|last_error|replace(_callback)?|grep|match(_all)?)\\\\b\",\n                    \"name\": \"support.function.php_pcre.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(spl_(classes|object_hash|autoload(_(call|unregister|extensions|functions|register))?)|class_(implements|uses|parents)|iterator_(count|to_array|apply))\\\\b\",\n                    \"name\": \"support.function.php_spl.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bzip_(close|open|entry_(name|compressionmethod|compressedsize|close|open|filesize|read)|read)\\\\b\",\n                    \"name\": \"support.function.php_zip.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nposix_(\\n  strerror|set(s|e?u|[ep]?g)id|ctermid|ttyname|times|isatty|initgroups|uname|errno|kill|access|\\n  get(sid|cwd|uid|pid|ppid|pwnam|pwuid|pgid|pgrp|euid|egid|login|rlimit|gid|grnam|groups|grgid)|\\n  get_last_error|mknod|mkfifo\\n)\\\\b\",\n                    \"name\": \"support.function.posix.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bset(thread|proc)title\\\\b\",\n                    \"name\": \"support.function.proctitle.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\npspell_(\\n  store_replacement|suggest|save_wordlist|new(_(config|personal))?|check|clear_session|\\n  config_(save_repl|create|ignore|(data|dict)_dir|personal|runtogether|repl|mode)|add_to_(session|personal)\\n)\\\\b\",\n                    \"name\": \"support.function.pspell.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\breadline(_(completion_function|clear_history|callback_(handler_(install|remove)|read_char)|info|on_new_line|write_history|list_history|add_history|redisplay|read_history))?\\\\b\",\n                    \"name\": \"support.function.readline.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\brecode(_(string|file))?\\\\b\",\n                    \"name\": \"support.function.recode.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\brrd(c_disconnect|_(create|tune|info|update|error|version|first|fetch|last(update)?|restore|graph|xport))\\\\b\",\n                    \"name\": \"support.function.rrd.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  shm_((get|has|remove|put)_var|detach|attach|remove)|sem_(acquire|release|remove|get)|ftok|\\n  msg_((get|remove|set|stat)_queue|send|queue_exists|receive)\\n)\\\\b\",\n                    \"name\": \"support.function.sem.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nsession_(\\n  status|start|set_(save_handler|cookie_params)|save_path|name|commit|cache_(expire|limiter)|\\n  is_registered|id|destroy|decode|unset|unregister|encode|write_close|abort|reset|register(_shutdown)?|\\n  regenerate_id|get_cookie_params|module_name\\n)\\\\b\",\n                    \"name\": \"support.function.session.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bshmop_(size|close|open|delete|write|read)\\\\b\",\n                    \"name\": \"support.function.shmop.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bsimplexml_(import_dom|load_(string|file))\\\\b\",\n                    \"name\": \"support.function.simplexml.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  snmp(walk(oid)?|realwalk|get(next)?|set)|\\n  snmp_(set_(valueretrieval|quick_print|enum_print|oid_(numeric_print|output_format))|read_mib|\\n        get_(valueretrieval|quick_print))|\\n  snmp[23]_(set|walk|real_walk|get(next)?)\\n)\\\\b\",\n                    \"name\": \"support.function.snmp.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\b(is_soap_fault|use_soap_error_handler)\\\\b\",\n                    \"name\": \"support.function.soap.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nsocket_(\\n  shutdown|strerror|send(to|msg)?|set_((non)?block|option)|select|connect|close|clear_error|bind|\\n  create(_(pair|listen))?|cmsg_space|import_stream|write|listen|last_error|accept|recv(from|msg)?|\\n  read|get(peer|sock)name|get_option\\n)\\\\b\",\n                    \"name\": \"support.function.sockets.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nsqlite_(\\n  single_query|seek|has_(more|prev)|num_(fields|rows)|next|changes|column|current|close|\\n  create_(aggregate|function)|open|unbuffered_query|udf_(decode|encode)_binary|popen|prev|\\n  escape_string|error_string|exec|valid|key|query|field_name|factory|\\n  fetch_(string|single|column_types|object|all|array)|lib(encoding|version)|\\n  last_(insert_rowid|error)|array_query|rewind|busy_timeout\\n)\\\\b\",\n                    \"name\": \"support.function.sqlite.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nsqlsrv_(\\n  send_stream_data|server_info|has_rows|num_(fields|rows)|next_result|connect|configure|commit|\\n  client_info|close|cancel|prepare|errors|execute|query|field_metadata|fetch(_(array|object))?|\\n  free_stmt|rows_affected|rollback|get_(config|field)|begin_transaction\\n)\\\\b\",\n                    \"name\": \"support.function.sqlsrv.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nstats_(\\n  harmonic_mean|covariance|standard_deviation|skew|\\n  cdf_(noncentral_(chisquare|f)|negative_binomial|chisquare|cauchy|t|uniform|poisson|exponential|f|weibull|\\n       logistic|laplace|gamma|binomial|beta)|\\n  stat_(noncentral_t|correlation|innerproduct|independent_t|powersum|percentile|paired_t|gennch|binomial_coef)|\\n  dens_(normal|negative_binomial|chisquare|cauchy|t|pmf_(hypergeometric|poisson|binomial)|exponential|f|\\n        weibull|logistic|laplace|gamma|beta)|\\n  den_uniform|variance|kurtosis|absolute_deviation|\\n  rand_(setall|phrase_to_seeds|ranf|get_seeds|\\n        gen_(noncentral_[ft]|noncenral_chisquare|normal|chisquare|t|int|\\n             i(uniform|poisson|binomial(_negative)?)|exponential|f(uniform)?|gamma|beta))\\n)\\\\b\",\n                    \"name\": \"support.function.stats.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  set_socket_blocking|\\n  stream_(socket_(shutdown|sendto|server|client|pair|enable_crypto|accept|recvfrom|get_name)|\\n    set_(chunk_size|timeout|(read|write)_buffer|blocking)|select|notification_callback|supports_lock|\\n    context_(set_(option|default|params)|create|get_(options|default|params))|copy_to_stream|is_local|\\n    encoding|filter_(append|prepend|register|remove)|wrapper_((un)?register|restore)|\\n    resolve_include_path|register_wrapper|get_(contents|transports|filters|wrappers|line|meta_data)|\\n    bucket_(new|prepend|append|make_writeable)\\n  )\\n)\\\\b\",\n                    \"name\": \"support.function.streamsfuncs.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  money_format|md5(_file)?|metaphone|bin2hex|sscanf|sha1(_file)?|\\n  str(str|c?spn|n(at)?(case)?cmp|chr|coll|(case)?cmp|to(upper|lower)|tok|tr|istr|pos|pbrk|len|rchr|ri?pos|rev)|\\n  str_(getcsv|ireplace|pad|repeat|replace|rot13|shuffle|split|word_count)|\\n  strip(c?slashes|os)|strip_tags|similar_text|soundex|substr(_(count|compare|replace))?|setlocale|\\n  html(specialchars(_decode)?|entities)|html_entity_decode|hex2bin|hebrev(c)?|number_format|nl2br|nl_langinfo|\\n  chop|chunk_split|chr|convert_(cyr_string|uu(decode|encode))|count_chars|crypt|crc32|trim|implode|ord|\\n  uc(first|words)|join|parse_str|print(f)?|echo|explode|v?[fs]?printf|quoted_printable_(decode|encode)|\\n  quotemeta|wordwrap|lcfirst|[lr]trim|localeconv|levenshtein|addc?slashes|get_html_translation_table\\n)\\\\b\",\n                    \"name\": \"support.function.string.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nsybase_(\\n  set_message_handler|select_db|num_(fields|rows)|connect|close|deadlock_retry_count|data_seek|\\n  unbuffered_query|pconnect|query|field_seek|fetch_(object|field|assoc|array|row)|free_result|\\n  affected_rows|result|get_last_message|min_(client|error|message|server)_severity\\n)\\\\b\",\n                    \"name\": \"support.function.sybase.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\b(taint|is_tainted|untaint)\\\\b\",\n                    \"name\": \"support.function.taint.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  tidy_((get|set)opt|set_encoding|save_config|config_count|clean_repair|is_(xhtml|xml)|diagnose|\\n        (access|error|warning)_count|load_config|reset_config|(parse|repair)_(string|file)|\\n        get_(status|html(_ver)?|head|config|output|opt_doc|root|release|body))|\\n  ob_tidyhandler\\n)\\\\b\",\n                    \"name\": \"support.function.tidy.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\btoken_(name|get_all)\\\\b\",\n                    \"name\": \"support.function.tokenizer.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\ntrader_(\\n  stoch(f|r|rsi)?|stddev|sin(h)?|sum|sub|set_(compat|unstable_period)|sqrt|sar(ext)?|sma|\\n  ht_(sine|trend(line|mode)|dc(period|phase)|phasor)|natr|cci|cos(h)?|correl|\\n  cdl(shootingstar|shortline|sticksandwich|stalledpattern|spinningtop|separatinglines|\\n      hikkake(mod)?|highwave|homingpigeon|hangingman|harami(cross)?|hammer|concealbabyswall|\\n      counterattack|closingmarubozu|thrusting|tasukigap|takuri|tristar|inneck|invertedhammer|\\n      identical3crows|2crows|onneck|doji(star)?|darkcloudcover|dragonflydoji|unique3river|\\n      upsidegap2crows|3(starsinsouth|inside|outside|whitesoldiers|linestrike|blackcrows)|\\n      piercing|engulfing|evening(doji)?star|kicking(bylength)?|longline|longleggeddoji|\\n      ladderbottom|advanceblock|abandonedbaby|risefall3methods|rickshawman|gapsidesidewhite|\\n      gravestonedoji|xsidegap3methods|morning(doji)?star|mathold|matchinglow|marubozu|\\n      belthold|breakaway)|\\n  ceil|cmo|tsf|typprice|t3|tema|tan(h)?|trix|trima|trange|obv|div|dema|dx|ultosc|ppo|\\n  plus_d[im]|errno|exp|ema|var|kama|floor|wclprice|willr|wma|ln|log10|bop|beta|bbands|\\n  linearreg(_(slope|intercept|angle))?|asin|acos|atan|atr|adosc|ad|add|adx(r)?|apo|avgprice|\\n  aroon(osc)?|rsi|roc|rocp|rocr(100)?|get_(compat|unstable_period)|min(index)?|minus_d[im]|\\n  minmax(index)?|mid(point|price)|mom|mult|medprice|mfi|macd(ext|fix)?|mavp|max(index)?|ma(ma)?\\n)\\\\b\",\n                    \"name\": \"support.function.trader.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\buopz_(copy|compose|implement|overload|delete|undefine|extend|function|flags|restore|rename|redefine|backup)\\\\b\",\n                    \"name\": \"support.function.uopz.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\b(http_build_query|(raw)?url(decode|encode)|parse_url|get_(headers|meta_tags)|base64_(decode|encode))\\\\b\",\n                    \"name\": \"support.function.url.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  strval|settype|serialize|(bool|double|float)val|debug_zval_dump|intval|import_request_variables|isset|\\n  is_(scalar|string|null|numeric|callable|int(eger)?|object|double|float|long|array|resource|real|bool)|\\n  unset|unserialize|print_r|empty|var_(dump|export)|gettype|get_(defined_vars|resource_type)\\n)\\\\b\",\n                    \"name\": \"support.function.var.php\"\n                },\n                {\n                    \"match\":\n                        \"(?i)\\\\bwddx_(serialize_(value|vars)|deserialize|packet_(start|end)|add_vars)\\\\b\",\n                    \"name\": \"support.function.wddx.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bxhprof_(sample_)?(disable|enable)\\\\b\",\n                    \"name\": \"support.function.xhprof.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\n\\\\b\\n(\\n  utf8_(decode|encode)|\\n  xml_(set_((notation|(end|start)_namespace|unparsed_entity)_decl_handler|\\n            (character_data|default|element|external_entity_ref|processing_instruction)_handler|object)|\\n       parse(_into_struct)?|parser_((get|set)_option|create(_ns)?|free)|error_string|\\n       get_(current_((column|line)_number|byte_index)|error_code))\\n)\\\\b\",\n                    \"name\": \"support.function.xml.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nxmlrpc_(\\n  server_(call_method|create|destroy|add_introspection_data|register_(introspection_callback|method))|\\n  is_fault|decode(_request)?|parse_method_descriptions|encode(_request)?|(get|set)_type\\n)\\\\b\",\n                    \"name\": \"support.function.xmlrpc.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\nxmlwriter_(\\n  (end|start|write)_(comment|cdata|dtd(_(attlist|entity|element))?|document|pi|attribute|element)|\\n  (start|write)_(attribute|element)_ns|write_raw|set_indent(_string)?|text|output_memory|open_(memory|uri)|\\n  full_end_element|flush|\\n)\\\\b\",\n                    \"name\": \"support.function.xmlwriter.php\"\n                },\n                {\n                    \"match\":\n                        \"(?xi)\\\\b\\n(\\n  zlib_(decode|encode|get_coding_type)|readgzfile|\\n  gz(seek|compress|close|tell|inflate|open|decode|deflate|uncompress|puts|passthru|encode|eof|file|\\n     write|rewind|read|getc|getss?)\\n)\\\\b\",\n                    \"name\": \"support.function.zlib.php\"\n                },\n                {\n                    \"match\": \"(?i)\\\\bis_int(eger)?\\\\b\",\n                    \"name\": \"support.function.alias.php\"\n                }\n            ]\n        },\n        \"switch_statement\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\s+(?=switch\\\\b)\"\n                },\n                {\n                    \"begin\": \"\\\\bswitch\\\\b(?!\\\\s*\\\\(.*\\\\)\\\\s*:)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.switch.php\"\n                        }\n                    },\n                    \"end\": \"}|(?=\\\\?>)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\":\n                                \"punctuation.definition.section.switch-block.end.bracket.curly.php\"\n                        }\n                    },\n                    \"name\": \"meta.switch-statement.php\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\(\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.switch-expression.begin.bracket.round.php\"\n                                }\n                            },\n                            \"end\": \"\\\\)|(?=\\\\?>)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.switch-expression.end.bracket.round.php\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"{\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.section.switch-block.begin.bracket.curly.php\"\n                                }\n                            },\n                            \"end\": \"(?=}|\\\\?>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"use-inner\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"begin\": \"(?i)\\\\b(as)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.other.use-as.php\"\n                        }\n                    },\n                    \"end\": \"(?i)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"entity.other.alias.php\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#class-name\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.php\"\n                }\n            ]\n        },\n        \"var_basic\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?i)(\\\\$+)[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*\",\n                    \"name\": \"variable.other.php\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"var_global\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.php\"\n                }\n            },\n            \"match\": \"(\\\\$)((_(COOKIE|FILES|GET|POST|REQUEST))|arg(v|c))\\\\b\",\n            \"name\": \"variable.other.global.php\"\n        },\n        \"var_global_safer\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.php\"\n                }\n            },\n            \"match\": \"(\\\\$)((GLOBALS|_(ENV|SERVER|SESSION)))\",\n            \"name\": \"variable.other.global.safer.php\"\n        },\n        \"var_language\": {\n            \"match\": \"(\\\\$)this\\\\b\",\n            \"name\": \"variable.language.this.php\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.php\"\n                }\n            }\n        },\n        \"variable-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#var_global\"\n                },\n                {\n                    \"include\": \"#var_global_safer\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.class.php\"\n                        },\n                        \"5\": {\n                            \"name\": \"variable.other.property.php\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.section.array.begin.php\"\n                        },\n                        \"7\": {\n                            \"name\": \"constant.numeric.index.php\"\n                        },\n                        \"8\": {\n                            \"name\": \"variable.other.index.php\"\n                        },\n                        \"9\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"10\": {\n                            \"name\": \"string.unquoted.index.php\"\n                        },\n                        \"11\": {\n                            \"name\": \"punctuation.section.array.end.php\"\n                        }\n                    },\n                    \"match\":\n                        \"(?xi)\\n((\\\\$)(?<name>[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*))\\n(?:\\n  (->)(\\\\g<name>)\\n  |\\n  (\\\\[)(?:(\\\\d+)|((\\\\$)\\\\g<name>)|([a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*))(\\\\])\\n)?\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.php\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"match\":\n                        \"(?i)((\\\\${)(?<name>[a-z_\\\\x{7f}-\\\\x{7fffffff}][a-z0-9_\\\\x{7f}-\\\\x{7fffffff}]*)(}))\"\n                }\n            ]\n        },\n        \"variables\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#var_language\"\n                },\n                {\n                    \"include\": \"#var_global\"\n                },\n                {\n                    \"include\": \"#var_global_safer\"\n                },\n                {\n                    \"include\": \"#var_basic\"\n                },\n                {\n                    \"begin\": \"\\\\${(?=.*?})\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.php\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"ternary_shorthand\": {\n            \"match\": \"\\\\?:\",\n            \"name\": \"keyword.operator.ternary.php\"\n        },\n        \"ternary_expression\": {\n            \"begin\": \"\\\\?\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.php\"\n                }\n            },\n            \"end\": \":\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.php\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"null_coalescing\": {\n            \"match\": \"\\\\?\\\\?\",\n            \"name\": \"keyword.operator.null-coalescing.php\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/python/syntaxes/python.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/MagicStack/MagicPython/blob/master/grammars/MagicPython.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/MagicStack/MagicPython/commit/b453f26ed856c9b16a053517c41207e3a72cc7d5\",\n    \"name\": \"MagicPython\",\n    \"scopeName\": \"source.python\",\n    \"patterns\": [\n        {\n            \"include\": \"#statement\"\n        },\n        {\n            \"include\": \"#expression\"\n        }\n    ],\n    \"repository\": {\n        \"impossible\": {\n            \"comment\":\n                \"This is a special rule that should be used where no match is desired. It is not a good idea to match something like '1{0}' because in some cases that can result in infinite loops in token generation. So the rule instead matches and impossible expression to allow a match to fail and move to the next token.\",\n            \"match\": \"$.^\"\n        },\n        \"statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#import\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#function-declaration\"\n                },\n                {\n                    \"include\": \"#statement-keyword\"\n                },\n                {\n                    \"include\": \"#assignment-operator\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#docstring-statement\"\n                },\n                {\n                    \"include\": \"#semicolon\"\n                }\n            ]\n        },\n        \"semicolon\": {\n            \"patterns\": [\n                {\n                    \"name\": \"invalid.deprecated.semicolon.python\",\n                    \"match\": \"\\\\;$\"\n                }\n            ]\n        },\n        \"comments\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.line.number-sign.python\",\n                    \"contentName\": \"meta.typehint.comment.python\",\n                    \"begin\":\n                        \"(?x)\\n  (?:\\n    \\\\# \\\\s* (type:)\\n    \\\\s*+ (?# we want `\\\\s*+` which is possessive quantifier since\\n             we do not actually want to backtrack when matching\\n             whitespace here)\\n    (?! $ | \\\\#)\\n  )\\n\",\n                    \"end\": \"(?:$|(?=\\\\#))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.typehint.comment.python\"\n                        },\n                        \"1\": {\n                            \"name\": \"comment.typehint.directive.notation.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"comment.typehint.ignore.notation.python\",\n                            \"match\": \"(?x)\\n  \\\\G ignore\\n  (?= \\\\s* (?: $ | \\\\#))\\n\"\n                        },\n                        {\n                            \"name\": \"comment.typehint.type.notation.python\",\n                            \"match\":\n                                \"(?x)\\n  (?<!\\\\.)\\\\b(\\n    bool | bytes | float | int | object | str\\n    | List | Dict | Iterable | Sequence | Set\\n    | FrozenSet | Callable | Union | Tuple\\n    | Any | None\\n  )\\\\b\\n\"\n                        },\n                        {\n                            \"name\": \"comment.typehint.punctuation.notation.python\",\n                            \"match\": \"([\\\\[\\\\]\\\\(\\\\),\\\\.\\\\=\\\\*]|(->))\"\n                        },\n                        {\n                            \"name\": \"comment.typehint.variable.notation.python\",\n                            \"match\": \"([[:alpha:]_]\\\\w*)\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comments-base\"\n                }\n            ]\n        },\n        \"docstring-statement\": {\n            \"begin\": \"^(?=\\\\s*[rR]?(\\\\'\\\\'\\\\'|\\\\\\\"\\\\\\\"\\\\\\\"|\\\\'|\\\\\\\"))\",\n            \"end\": \"(?<=\\\\'\\\\'\\\\'|\\\\\\\"\\\\\\\"\\\\\\\"|\\\\'|\\\\\\\")\",\n            \"patterns\": [\n                {\n                    \"include\": \"#docstring\"\n                }\n            ]\n        },\n        \"docstring\": {\n            \"patterns\": [\n                {\n                    \"name\": \"string.quoted.docstring.multi.python\",\n                    \"begin\": \"(\\\\'\\\\'\\\\'|\\\\\\\"\\\\\\\"\\\\\\\")\",\n                    \"end\": \"(\\\\1)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.python\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#docstring-prompt\"\n                        },\n                        {\n                            \"include\": \"#codetags\"\n                        },\n                        {\n                            \"include\": \"#docstring-guts-unicode\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.quoted.docstring.raw.multi.python\",\n                    \"begin\": \"([rR])(\\\\'\\\\'\\\\'|\\\\\\\"\\\\\\\"\\\\\\\")\",\n                    \"end\": \"(\\\\2)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.string.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.string.begin.python\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#string-consume-escape\"\n                        },\n                        {\n                            \"include\": \"#docstring-prompt\"\n                        },\n                        {\n                            \"include\": \"#codetags\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.quoted.docstring.single.python\",\n                    \"begin\": \"(\\\\'|\\\\\\\")\",\n                    \"end\": \"(\\\\1)|((?<!\\\\\\\\)\\\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.python\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.newline.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#codetags\"\n                        },\n                        {\n                            \"include\": \"#docstring-guts-unicode\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.quoted.docstring.raw.single.python\",\n                    \"begin\": \"([rR])(\\\\'|\\\\\\\")\",\n                    \"end\": \"(\\\\2)|((?<!\\\\\\\\)\\\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.string.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.string.begin.python\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.newline.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#string-consume-escape\"\n                        },\n                        {\n                            \"include\": \"#codetags\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"docstring-guts-unicode\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#escape-sequence\"\n                },\n                {\n                    \"include\": \"#string-line-continuation\"\n                }\n            ]\n        },\n        \"docstring-prompt\": {\n            \"match\":\n                \"(?x)\\n  (?:\\n    (?:^|\\\\G) \\\\s* (?# '\\\\G' is necessary for ST)\\n    ((?:>>>|\\\\.\\\\.\\\\.) \\\\s) (?=\\\\s*\\\\S)\\n  )\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.flow.python\"\n                }\n            }\n        },\n        \"statement-keyword\": {\n            \"patterns\": [\n                {\n                    \"name\": \"storage.type.function.python\",\n                    \"match\": \"\\\\b((async\\\\s+)?\\\\s*def)\\\\b\"\n                },\n                {\n                    \"name\": \"keyword.control.flow.python\",\n                    \"match\":\n                        \"(?x)\\n  \\\\b(?<!\\\\.)(\\n    as | async | continue | del | assert | break | finally | for\\n    | from | elif | else | if | except | pass | raise\\n    | return | try | while | with\\n  )\\\\b\\n\"\n                },\n                {\n                    \"name\": \"storage.modifier.declaration.python\",\n                    \"match\": \"(?x)\\n  \\\\b(?<!\\\\.)(\\n    global | nonlocal\\n  )\\\\b\\n\"\n                },\n                {\n                    \"name\": \"storage.type.class.python\",\n                    \"match\": \"\\\\b(?<!\\\\.)(class)\\\\b\"\n                }\n            ]\n        },\n        \"expression-bare\": {\n            \"comment\": \"valid Python expressions w/o comments and line continuation\",\n            \"patterns\": [\n                {\n                    \"include\": \"#backticks\"\n                },\n                {\n                    \"include\": \"#illegal-anno\"\n                },\n                {\n                    \"include\": \"#literal\"\n                },\n                {\n                    \"include\": \"#regexp\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#lambda\"\n                },\n                {\n                    \"include\": \"#illegal-operator\"\n                },\n                {\n                    \"include\": \"#operator\"\n                },\n                {\n                    \"include\": \"#curly-braces\"\n                },\n                {\n                    \"include\": \"#item-access\"\n                },\n                {\n                    \"include\": \"#list\"\n                },\n                {\n                    \"include\": \"#round-braces\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#builtin-functions\"\n                },\n                {\n                    \"include\": \"#builtin-types\"\n                },\n                {\n                    \"include\": \"#builtin-exceptions\"\n                },\n                {\n                    \"include\": \"#magic-names\"\n                },\n                {\n                    \"include\": \"#special-names\"\n                },\n                {\n                    \"include\": \"#illegal-names\"\n                },\n                {\n                    \"include\": \"#special-variables\"\n                },\n                {\n                    \"include\": \"#ellipsis\"\n                },\n                {\n                    \"include\": \"#punctuation\"\n                },\n                {\n                    \"include\": \"#line-continuation\"\n                }\n            ]\n        },\n        \"expression-base\": {\n            \"comment\": \"valid Python expressions with comments and line continuation\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"include\": \"#expression-bare\"\n                },\n                {\n                    \"include\": \"#line-continuation\"\n                }\n            ]\n        },\n        \"expression\": {\n            \"comment\": \"All valid Python expressions\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression-base\"\n                },\n                {\n                    \"include\": \"#member-access\"\n                },\n                {\n                    \"comment\": \"Tokenize identifiers to help linters\",\n                    \"match\": \"(?x) \\\\b ([[:alpha:]_]\\\\w*) \\\\b\"\n                }\n            ]\n        },\n        \"member-access\": {\n            \"begin\": \"(\\\\.)\\\\s*(?!\\\\.)\",\n            \"end\":\n                \"(?x)\\n  # stop when you've just read non-whitespace followed by non-word\\n  # i.e. when finished reading an identifier or function call\\n  (?<=\\\\S)(?=\\\\W) |\\n  # stop when seeing the start of something that's not a word,\\n  # i.e. when seeing a non-identifier\\n  (^|(?<=\\\\s))(?=[^\\\\\\\\\\\\w\\\\s]) |\\n  $\\n\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.period.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#member-access-base\"\n                }\n            ]\n        },\n        \"member-access-base\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#magic-names\"\n                },\n                {\n                    \"include\": \"#illegal-names\"\n                },\n                {\n                    \"include\": \"#illegal-object-name\"\n                },\n                {\n                    \"include\": \"#special-names\"\n                },\n                {\n                    \"include\": \"#line-continuation\"\n                },\n                {\n                    \"include\": \"#item-access\"\n                }\n            ]\n        },\n        \"special-names\": {\n            \"name\": \"constant.other.caps.python\",\n            \"match\":\n                \"(?x)\\n  \\\\b\\n    # we want to see \\\"enough\\\", meaning 2 or more upper-case\\n    # letters in the beginning of the constant\\n    #\\n    # for more details refer to:\\n    #   https://github.com/MagicStack/MagicPython/issues/42\\n    (\\n      _* [[:upper:]] [_\\\\d]* [[:upper:]]\\n    )\\n    [[:upper:]\\\\d]* (_\\\\w*)?\\n  \\\\b\\n\"\n        },\n        \"curly-braces\": {\n            \"begin\": \"\\\\{\",\n            \"end\": \"\\\\}\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.dict.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.dict.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"punctuation.separator.dict.python\",\n                    \"match\": \":\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"list\": {\n            \"begin\": \"\\\\[\",\n            \"end\": \"\\\\]\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.list.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.list.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"round-braces\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"\\\\)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.parenthesis.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"line-continuation\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(\\\\\\\\)\\\\s*(\\\\S.*$\\\\n?)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.continuation.line.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.line.continuation.python\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(\\\\\\\\)\\\\s*$\\\\n?\",\n                    \"end\":\n                        \"(?x)\\n  (?=^\\\\s*$)\\n  |\\n  (?! (\\\\s* [rR]? (\\\\'\\\\'\\\\'|\\\\\\\"\\\\\\\"\\\\\\\"|\\\\'|\\\\\\\"))\\n      |\\n      (\\\\G $)  (?# '\\\\G' is necessary for ST)\\n  )\\n\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.continuation.line.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"assignment-operator\": {\n            \"name\": \"keyword.operator.assignment.python\",\n            \"match\":\n                \"(?x)\\n     <<= | >>= | //= | \\\\*\\\\*=\\n    | \\\\+= | -= | /= | @=\\n    | \\\\*= | %= | ~= | \\\\^= | &= | \\\\|=\\n    | =(?!=)\\n\"\n        },\n        \"operator\": {\n            \"match\":\n                \"(?x)\\n    \\\\b(?<!\\\\.)\\n      (?:\\n        (and | or | not | in | is)                         (?# 1)\\n        |\\n        (for | if | else | await | (?:yield(?:\\\\s+from)?))  (?# 2)\\n      )\\n    (?!\\\\s*:)\\\\b\\n\\n    | (<< | >> | & | \\\\| | \\\\^ | ~)                          (?# 3)\\n\\n    | (\\\\*\\\\* | \\\\* | \\\\+ | - | % | // | / | @)                (?# 4)\\n\\n    | (!= | == | >= | <= | < | >)                          (?# 5)\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.logical.python\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.flow.python\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.operator.bitwise.python\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.operator.arithmetic.python\"\n                },\n                \"5\": {\n                    \"name\": \"keyword.operator.comparison.python\"\n                }\n            }\n        },\n        \"punctuation\": {\n            \"patterns\": [\n                {\n                    \"name\": \"punctuation.separator.colon.python\",\n                    \"match\": \":\"\n                },\n                {\n                    \"name\": \"punctuation.separator.element.python\",\n                    \"match\": \",\"\n                }\n            ]\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.python\",\n                    \"match\": \"\\\\b(True|False|None|NotImplemented|Ellipsis)\\\\b\"\n                },\n                {\n                    \"include\": \"#number\"\n                }\n            ]\n        },\n        \"number\": {\n            \"name\": \"constant.numeric.python\",\n            \"patterns\": [\n                {\n                    \"include\": \"#number-float\"\n                },\n                {\n                    \"include\": \"#number-dec\"\n                },\n                {\n                    \"include\": \"#number-hex\"\n                },\n                {\n                    \"include\": \"#number-oct\"\n                },\n                {\n                    \"include\": \"#number-bin\"\n                },\n                {\n                    \"include\": \"#number-long\"\n                },\n                {\n                    \"name\": \"invalid.illegal.name.python\",\n                    \"match\": \"\\\\b[0-9]+\\\\w+\"\n                }\n            ]\n        },\n        \"number-float\": {\n            \"name\": \"constant.numeric.float.python\",\n            \"match\":\n                \"(?x)\\n  (?<! \\\\w)(?:\\n    (?:\\n      \\\\.[0-9](?: _?[0-9] )*\\n      |\\n      [0-9](?: _?[0-9] )* \\\\. [0-9](?: _?[0-9] )*\\n      |\\n      [0-9](?: _?[0-9] )* \\\\.\\n    ) (?: [eE][+-]?[0-9](?: _?[0-9] )* )?\\n    |\\n    [0-9](?: _?[0-9] )* (?: [eE][+-]?[0-9](?: _?[0-9] )* )\\n  )([jJ])?\\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.imaginary.number.python\"\n                }\n            }\n        },\n        \"number-dec\": {\n            \"name\": \"constant.numeric.dec.python\",\n            \"match\":\n                \"(?x)\\n  (?<![\\\\w\\\\.])(?:\\n      [1-9](?: _?[0-9] )*\\n      |\\n      0+\\n      |\\n      [0-9](?: _?[0-9] )* ([jJ])\\n      |\\n      0 ([0-9]+)(?![eE\\\\.])\\n  )\\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.imaginary.number.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.dec.python\"\n                },\n                \"3\": {\n                    \"name\": \"invalid.illegal.dec.python\"\n                }\n            }\n        },\n        \"number-hex\": {\n            \"name\": \"constant.numeric.hex.python\",\n            \"match\": \"(?x)\\n  (?<![\\\\w\\\\.])\\n    (0[xX]) (_?[0-9a-fA-F])+\\n  \\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.number.python\"\n                }\n            }\n        },\n        \"number-oct\": {\n            \"name\": \"constant.numeric.oct.python\",\n            \"match\": \"(?x)\\n  (?<![\\\\w\\\\.])\\n    (0[oO]) (_?[0-7])+\\n  \\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.number.python\"\n                }\n            }\n        },\n        \"number-bin\": {\n            \"name\": \"constant.numeric.bin.python\",\n            \"match\": \"(?x)\\n  (?<![\\\\w\\\\.])\\n    (0[bB]) (_?[01])+\\n  \\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.type.number.python\"\n                }\n            }\n        },\n        \"number-long\": {\n            \"name\": \"constant.numeric.bin.python\",\n            \"comment\": \"this is to support python2 syntax for long ints\",\n            \"match\": \"(?x)\\n  (?<![\\\\w\\\\.])\\n    ([1-9][0-9]* | 0) ([lL])\\n  \\\\b\\n\",\n            \"captures\": {\n                \"2\": {\n                    \"name\": \"storage.type.number.python\"\n                }\n            }\n        },\n        \"regexp\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-single-three-line\"\n                },\n                {\n                    \"include\": \"#regexp-double-three-line\"\n                },\n                {\n                    \"include\": \"#regexp-single-one-line\"\n                },\n                {\n                    \"include\": \"#regexp-double-one-line\"\n                },\n                {\n                    \"include\": \"#fregexp-single-three-line\"\n                },\n                {\n                    \"include\": \"#fregexp-double-three-line\"\n                },\n                {\n                    \"include\": \"#fregexp-single-one-line\"\n                },\n                {\n                    \"include\": \"#fregexp-double-one-line\"\n                }\n            ]\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#string-quoted-single-line\"\n                },\n                {\n                    \"include\": \"#string-bin-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#string-bin-quoted-single-line\"\n                },\n                {\n                    \"include\": \"#string-raw-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#string-raw-quoted-single-line\"\n                },\n                {\n                    \"include\": \"#string-raw-bin-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#string-raw-bin-quoted-single-line\"\n                },\n                {\n                    \"include\": \"#fstring-fnorm-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#fstring-fnorm-quoted-single-line\"\n                },\n                {\n                    \"include\": \"#fstring-normf-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#fstring-normf-quoted-single-line\"\n                },\n                {\n                    \"include\": \"#fstring-raw-quoted-multi-line\"\n                },\n                {\n                    \"include\": \"#fstring-raw-quoted-single-line\"\n                }\n            ]\n        },\n        \"string-unicode-guts\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#string-entity\"\n                },\n                {\n                    \"include\": \"#string-brace-formatting\"\n                }\n            ]\n        },\n        \"string-consume-escape\": {\n            \"match\": \"\\\\\\\\['\\\"\\\\n\\\\\\\\]\"\n        },\n        \"string-raw-guts\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                },\n                {\n                    \"include\": \"#string-formatting\"\n                },\n                {\n                    \"include\": \"#string-brace-formatting\"\n                }\n            ]\n        },\n        \"string-raw-bin-guts\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                },\n                {\n                    \"include\": \"#string-formatting\"\n                }\n            ]\n        },\n        \"string-entity\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence\"\n                },\n                {\n                    \"include\": \"#string-line-continuation\"\n                },\n                {\n                    \"include\": \"#string-formatting\"\n                }\n            ]\n        },\n        \"fstring-guts\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#escape-sequence\"\n                },\n                {\n                    \"include\": \"#string-line-continuation\"\n                },\n                {\n                    \"include\": \"#fstring-formatting\"\n                }\n            ]\n        },\n        \"fstring-raw-guts\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                },\n                {\n                    \"include\": \"#fstring-formatting\"\n                }\n            ]\n        },\n        \"fstring-illegal-single-brace\": {\n            \"comment\": \"it is illegal to have a multiline brace inside a single-line string\",\n            \"begin\": \"(\\\\{)(?=[^\\\\n}]*$\\\\n?)\",\n            \"end\": \"(\\\\})|(?=\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"constant.character.format.placeholder.other.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"constant.character.format.placeholder.other.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-terminator-single\"\n                },\n                {\n                    \"include\": \"#f-expression\"\n                }\n            ]\n        },\n        \"fstring-illegal-multi-brace\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#impossible\"\n                }\n            ]\n        },\n        \"f-expression\": {\n            \"comment\": \"All valid Python expressions, except comments and line cont\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression-bare\"\n                },\n                {\n                    \"include\": \"#member-access\"\n                },\n                {\n                    \"comment\": \"Tokenize identifiers to help linters\",\n                    \"match\": \"(?x) \\\\b ([[:alpha:]_]\\\\w*) \\\\b\"\n                }\n            ]\n        },\n        \"escape-sequence-unicode\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.escape.python\",\n                    \"match\":\n                        \"(?x)\\n  \\\\\\\\ (\\n        u[0-9A-Fa-f]{4}\\n        | U[0-9A-Fa-f]{8}\\n        | N\\\\{[\\\\w\\\\s]+?\\\\}\\n     )\\n\"\n                }\n            ]\n        },\n        \"escape-sequence\": {\n            \"name\": \"constant.character.escape.python\",\n            \"match\":\n                \"(?x)\\n  \\\\\\\\ (\\n        x[0-9A-Fa-f]{2}\\n        | [0-7]{1,3}\\n        | [\\\\\\\\\\\"'abfnrtv]\\n     )\\n\"\n        },\n        \"string-line-continuation\": {\n            \"name\": \"constant.language.python\",\n            \"match\": \"\\\\\\\\$\"\n        },\n        \"string-formatting\": {\n            \"name\": \"constant.character.format.placeholder.other.python\",\n            \"match\":\n                \"(?x)\\n  % (\\\\([\\\\w\\\\s]*\\\\))?\\n    [-+#0 ]*\\n    (\\\\d+|\\\\*)? (\\\\.(\\\\d+|\\\\*))?\\n    ([hlL])?\\n    [diouxXeEfFgGcrsa%]\\n\"\n        },\n        \"string-brace-formatting\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.format.placeholder.other.python\",\n                    \"match\":\n                        \"(?x)\\n  (?:\\n    {{ | }}\\n    | (?:\\n      {\\n        \\\\w*? (\\\\.[[:alpha:]_]\\\\w*? | \\\\[[^\\\\]'\\\"]+\\\\])*?\\n        (![rsa])?\\n        ( : \\\\w? [<>=^]? [-+ ]? \\\\#?\\n          \\\\d* ,? (\\\\.\\\\d+)? [bcdeEfFgGnosxX%]? )?\\n      })\\n  )\\n\",\n                    \"captures\": {\n                        \"2\": {\n                            \"name\": \"storage.type.format.python\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.format.python\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"constant.character.format.placeholder.other.python\",\n                    \"begin\":\n                        \"(?x)\\n    \\\\{\\n      \\\\w*? (\\\\.[[:alpha:]_]\\\\w*? | \\\\[[^\\\\]'\\\"]+\\\\])*?\\n      (![rsa])?\\n      (:)\\n        (?=[^'\\\"}\\\\n]*\\\\})\\n\",\n                    \"end\": \"\\\\}\",\n                    \"beginCaptures\": {\n                        \"2\": {\n                            \"name\": \"storage.type.format.python\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.format.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"(?x) \\\\{ [^'\\\"}\\\\n]*? \\\\} (?=.*?\\\\})\\n\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"fstring-formatting\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-formatting-braces\"\n                },\n                {\n                    \"include\": \"#fstring-formatting-singe-brace\"\n                }\n            ]\n        },\n        \"fstring-formatting-singe-brace\": {\n            \"name\": \"invalid.illegal.brace.python\",\n            \"match\": \"(}(?!}))\"\n        },\n        \"import\": {\n            \"comment\": \"Import statements\\n\",\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n  \\\\s* \\\\b(from)\\\\b \\\\s*(\\\\.+)\\\\s* (import)?\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.import.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.period.python\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.import.python\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"keyword.control.import.python\",\n                    \"match\": \"\\\\b(?<!\\\\.)import\\\\b\"\n                }\n            ]\n        },\n        \"class-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.class.python\",\n                    \"begin\":\n                        \"(?x)\\n  \\\\s*(class)\\\\s+\\n    (?=\\n      [[:alpha:]_]\\\\w* \\\\s* (:|\\\\()\\n    )\\n\",\n                    \"end\": \"(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.python\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.class.begin.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#class-name\"\n                        },\n                        {\n                            \"include\": \"#class-inheritance\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"class-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#illegal-object-name\"\n                },\n                {\n                    \"include\": \"#builtin-possible-callables\"\n                },\n                {\n                    \"name\": \"entity.name.type.class.python\",\n                    \"match\": \"(?x)\\n  \\\\b ([[:alpha:]_]\\\\w*) \\\\b\\n\"\n                }\n            ]\n        },\n        \"class-inheritance\": {\n            \"name\": \"meta.class.inheritance.python\",\n            \"begin\": \"(\\\\()\",\n            \"end\": \"(\\\\))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.inheritance.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.inheritance.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.operator.unpacking.arguments.python\",\n                    \"match\": \"(\\\\*\\\\*|\\\\*)\"\n                },\n                {\n                    \"name\": \"punctuation.separator.inheritance.python\",\n                    \"match\": \",\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.python\",\n                    \"match\": \"=(?!=)\"\n                },\n                {\n                    \"name\": \"support.type.metaclass.python\",\n                    \"match\": \"\\\\bmetaclass\\\\b\"\n                },\n                {\n                    \"include\": \"#illegal-names\"\n                },\n                {\n                    \"include\": \"#class-kwarg\"\n                },\n                {\n                    \"include\": \"#call-wrapper-inheritance\"\n                },\n                {\n                    \"include\": \"#expression-base\"\n                },\n                {\n                    \"include\": \"#member-access-class\"\n                },\n                {\n                    \"include\": \"#inheritance-identifier\"\n                }\n            ]\n        },\n        \"class-kwarg\": {\n            \"match\": \"(?x)\\n  \\\\b ([[:alpha:]_]\\\\w*) \\\\s*(=)(?!=)\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.inherited-class.python variable.parameter.class.python\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.assignment.python\"\n                }\n            }\n        },\n        \"inheritance-identifier\": {\n            \"match\": \"(?x)\\n  \\\\b ([[:alpha:]_]\\\\w*) \\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.inherited-class.python\"\n                }\n            }\n        },\n        \"member-access-class\": {\n            \"begin\": \"(\\\\.)\\\\s*(?!\\\\.)\",\n            \"end\": \"(?<=\\\\S)(?=\\\\W)|$\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.period.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#call-wrapper-inheritance\"\n                },\n                {\n                    \"include\": \"#member-access-base\"\n                },\n                {\n                    \"include\": \"#inheritance-identifier\"\n                }\n            ]\n        },\n        \"lambda\": {\n            \"patterns\": [\n                {\n                    \"match\": \"((?<=\\\\.)lambda|lambda(?=\\\\s*[\\\\.=]))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.flow.python\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"\\\\b(lambda)\\\\s*?(?=[,\\\\n]|$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.lambda.python\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.lambda-function.python\",\n                    \"begin\": \"(?x)\\n  \\\\b (lambda) \\\\b\\n\",\n                    \"end\": \"(:)|(\\\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.lambda.python\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.function.lambda.begin.python\"\n                        }\n                    },\n                    \"contentName\": \"meta.function.lambda.parameters.python\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"keyword.operator.unpacking.parameter.python\",\n                            \"match\": \"(\\\\*\\\\*|\\\\*)\"\n                        },\n                        {\n                            \"include\": \"#lambda-nested-incomplete\"\n                        },\n                        {\n                            \"include\": \"#illegal-names\"\n                        },\n                        {\n                            \"match\": \"([[:alpha:]_]\\\\w*)\\\\s*(?:(,)|(?=:|$))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.parameter.function.language.python\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.parameters.python\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#comments\"\n                        },\n                        {\n                            \"include\": \"#backticks\"\n                        },\n                        {\n                            \"include\": \"#illegal-anno\"\n                        },\n                        {\n                            \"include\": \"#lambda-parameter-with-default\"\n                        },\n                        {\n                            \"include\": \"#line-continuation\"\n                        },\n                        {\n                            \"include\": \"#illegal-operator\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"lambda-incomplete\": {\n            \"name\": \"storage.type.function.lambda.python\",\n            \"match\": \"\\\\blambda(?=\\\\s*[,)])\"\n        },\n        \"lambda-nested-incomplete\": {\n            \"name\": \"storage.type.function.lambda.python\",\n            \"match\": \"\\\\blambda(?=\\\\s*[:,)])\"\n        },\n        \"lambda-parameter-with-default\": {\n            \"begin\": \"(?x)\\n  \\\\b\\n  ([[:alpha:]_]\\\\w*) \\\\s* (=)\\n\",\n            \"end\": \"(,)|(?=:|$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"variable.parameter.function.language.python\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.parameters.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"function-declaration\": {\n            \"name\": \"meta.function.python\",\n            \"begin\":\n                \"(?x)\\n  \\\\s*\\n  (?:\\\\b(async) \\\\s+)? \\\\b(def)\\\\s+\\n    (?=\\n      [[:alpha:]_][[:word:]]* \\\\s* \\\\(\\n    )\\n\",\n            \"end\": \"(:|(?=[#'\\\"\\\\n]))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.function.async.python\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.function.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.function.begin.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#function-def-name\"\n                },\n                {\n                    \"include\": \"#parameters\"\n                },\n                {\n                    \"include\": \"#line-continuation\"\n                },\n                {\n                    \"include\": \"#return-annotation\"\n                }\n            ]\n        },\n        \"function-def-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#illegal-object-name\"\n                },\n                {\n                    \"include\": \"#builtin-possible-callables\"\n                },\n                {\n                    \"name\": \"entity.name.function.python\",\n                    \"match\": \"(?x)\\n  \\\\b ([[:alpha:]_]\\\\w*) \\\\b\\n\"\n                }\n            ]\n        },\n        \"parameters\": {\n            \"name\": \"meta.function.parameters.python\",\n            \"begin\": \"(\\\\()\",\n            \"end\": \"(\\\\))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.parameters.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.parameters.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.operator.unpacking.parameter.python\",\n                    \"match\": \"(\\\\*\\\\*|\\\\*)\"\n                },\n                {\n                    \"include\": \"#lambda-incomplete\"\n                },\n                {\n                    \"include\": \"#illegal-names\"\n                },\n                {\n                    \"include\": \"#illegal-object-name\"\n                },\n                {\n                    \"include\": \"#parameter-special\"\n                },\n                {\n                    \"match\": \"(?x)\\n  ([[:alpha:]_]\\\\w*)\\n    \\\\s* (?: (,) | (?=[)#\\\\n=]))\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.parameter.function.language.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.parameters.python\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#comments\"\n                },\n                {\n                    \"include\": \"#loose-default\"\n                },\n                {\n                    \"include\": \"#annotated-parameter\"\n                }\n            ]\n        },\n        \"parameter-special\": {\n            \"match\": \"(?x)\\n  \\\\b ((self)|(cls)) \\\\b \\\\s*(?:(,)|(?=\\\\)))\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"variable.parameter.function.language.python\"\n                },\n                \"2\": {\n                    \"name\": \"variable.parameter.function.language.special.self.python\"\n                },\n                \"3\": {\n                    \"name\": \"variable.parameter.function.language.special.cls.python\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.separator.parameters.python\"\n                }\n            }\n        },\n        \"loose-default\": {\n            \"begin\": \"(=)\",\n            \"end\": \"(,)|(?=\\\\))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.parameters.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"annotated-parameter\": {\n            \"begin\": \"(?x)\\n  \\\\b\\n  ([[:alpha:]_]\\\\w*) \\\\s* (:)\\n\",\n            \"end\": \"(,)|(?=\\\\))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"variable.parameter.function.language.python\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.separator.annotation.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.parameters.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.python\",\n                    \"match\": \"=(?!=)\"\n                }\n            ]\n        },\n        \"return-annotation\": {\n            \"begin\": \"(->)\",\n            \"end\": \"(?=:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.annotation.result.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"item-access\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.item-access.python\",\n                    \"begin\": \"(?x)\\n  \\\\b(?=\\n    [[:alpha:]_]\\\\w* \\\\s* \\\\[\\n  )\\n\",\n                    \"end\": \"(\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.arguments.end.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#item-name\"\n                        },\n                        {\n                            \"include\": \"#item-index\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"item-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#special-variables\"\n                },\n                {\n                    \"include\": \"#builtin-functions\"\n                },\n                {\n                    \"include\": \"#special-names\"\n                },\n                {\n                    \"match\": \"(?x)\\n  \\\\b ([[:alpha:]_]\\\\w*) \\\\b\\n\"\n                }\n            ]\n        },\n        \"item-index\": {\n            \"begin\": \"(\\\\[)\",\n            \"end\": \"(?=\\\\])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.arguments.begin.python\"\n                }\n            },\n            \"contentName\": \"meta.item-access.arguments.python\",\n            \"patterns\": [\n                {\n                    \"name\": \"punctuation.separator.slice.python\",\n                    \"match\": \":\"\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"decorator\": {\n            \"name\": \"meta.function.decorator.python\",\n            \"begin\": \"(?x)\\n  ^\\\\s*\\n  (@) \\\\s* (?=[[:alpha:]_]\\\\w*)\\n\",\n            \"end\":\n                \"(?x)\\n  ( \\\\) )\\n    # trailing whitespace and comments are legal\\n    (?: (.*?) (?=\\\\s*(?:\\\\#|$)) )\\n  | (?=\\\\n|\\\\#)\\n\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.decorator.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.arguments.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.decorator.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#decorator-name\"\n                },\n                {\n                    \"include\": \"#function-arguments\"\n                }\n            ]\n        },\n        \"decorator-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#builtin-callables\"\n                },\n                {\n                    \"include\": \"#illegal-object-name\"\n                },\n                {\n                    \"name\": \"entity.name.function.decorator.python\",\n                    \"match\": \"(?x)\\n  ([[:alpha:]_]\\\\w*) | \\\\.\\n\"\n                },\n                {\n                    \"include\": \"#line-continuation\"\n                },\n                {\n                    \"name\": \"invalid.illegal.decorator.python\",\n                    \"match\": \"(?x)\\n  \\\\s* ([^([:alpha:]\\\\s_\\\\.#\\\\\\\\] .*?) (?=\\\\#|$)\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"invalid.illegal.decorator.python\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"call-wrapper-inheritance\": {\n            \"comment\": \"same as a function call, but in inheritance context\",\n            \"name\": \"meta.function-call.python\",\n            \"begin\": \"(?x)\\n  \\\\b(?=\\n    ([[:alpha:]_]\\\\w*) \\\\s* (\\\\()\\n  )\\n\",\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.arguments.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#inheritance-name\"\n                },\n                {\n                    \"include\": \"#function-arguments\"\n                }\n            ]\n        },\n        \"inheritance-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#lambda-incomplete\"\n                },\n                {\n                    \"include\": \"#builtin-possible-callables\"\n                },\n                {\n                    \"include\": \"#inheritance-identifier\"\n                }\n            ]\n        },\n        \"function-call\": {\n            \"name\": \"meta.function-call.python\",\n            \"begin\": \"(?x)\\n  \\\\b(?=\\n    ([[:alpha:]_]\\\\w*) \\\\s* (\\\\()\\n  )\\n\",\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.arguments.end.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#special-variables\"\n                },\n                {\n                    \"include\": \"#function-name\"\n                },\n                {\n                    \"include\": \"#function-arguments\"\n                }\n            ]\n        },\n        \"function-name\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#builtin-possible-callables\"\n                },\n                {\n                    \"comment\": \"Some color schemas support meta.function-call.generic scope\",\n                    \"name\": \"meta.function-call.generic.python\",\n                    \"match\": \"(?x)\\n  \\\\b ([[:alpha:]_]\\\\w*) \\\\b\\n\"\n                }\n            ]\n        },\n        \"function-arguments\": {\n            \"begin\": \"(?x)\\n  (?:\\n    (\\\\()\\n    (?:\\\\s*(\\\\*\\\\*|\\\\*))?\\n  )\\n\",\n            \"end\": \"(?=\\\\))(?!\\\\)\\\\s*\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.arguments.begin.python\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.unpacking.arguments.python\"\n                }\n            },\n            \"contentName\": \"meta.function-call.arguments.python\",\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n  (?:\\n    (,)\\n    (?:\\\\s*(\\\\*\\\\*|\\\\*))?\\n  )\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.arguments.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.unpacking.arguments.python\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#lambda-incomplete\"\n                },\n                {\n                    \"include\": \"#illegal-names\"\n                },\n                {\n                    \"match\": \"\\\\b([[:alpha:]_]\\\\w*)\\\\s*(=)(?!=)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.parameter.function-call.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.assignment.python\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.python\",\n                    \"match\": \"=(?!=)\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"match\": \"\\\\s*(\\\\))\\\\s*(\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.arguments.end.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.arguments.begin.python\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"builtin-callables\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#illegal-names\"\n                },\n                {\n                    \"include\": \"#illegal-object-name\"\n                },\n                {\n                    \"include\": \"#builtin-exceptions\"\n                },\n                {\n                    \"include\": \"#builtin-functions\"\n                },\n                {\n                    \"include\": \"#builtin-types\"\n                }\n            ]\n        },\n        \"builtin-possible-callables\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#builtin-callables\"\n                },\n                {\n                    \"include\": \"#magic-names\"\n                }\n            ]\n        },\n        \"builtin-exceptions\": {\n            \"name\": \"support.type.exception.python\",\n            \"match\":\n                \"(?x) (?<!\\\\.) \\\\b(\\n  (\\n    Arithmetic | Assertion | Attribute | Buffer | BlockingIO\\n    | BrokenPipe | ChildProcess\\n    | (Connection (Aborted | Refused | Reset)?)\\n    | EOF | Environment | FileExists | FileNotFound\\n    | FloatingPoint | IO | Import | Indentation | Index | Interrupted\\n    | IsADirectory | NotADirectory | Permission | ProcessLookup\\n    | Timeout\\n    | Key | Lookup | Memory | Name | NotImplemented | OS | Overflow\\n    | Reference | Runtime | Recursion | Syntax | System\\n    | Tab | Type | UnboundLocal | Unicode(Encode|Decode|Translate)?\\n    | Value | Windows | ZeroDivision | ModuleNotFound\\n  ) Error\\n|\\n  ((Pending)?Deprecation | Runtime | Syntax | User | Future | Import\\n    | Unicode | Bytes | Resource\\n  )? Warning\\n|\\n  SystemExit | Stop(Async)?Iteration\\n  | KeyboardInterrupt\\n  | GeneratorExit | (Base)?Exception\\n)\\\\b\\n\"\n        },\n        \"builtin-functions\": {\n            \"patterns\": [\n                {\n                    \"name\": \"support.function.builtin.python\",\n                    \"match\":\n                        \"(?x)\\n  (?<!\\\\.) \\\\b(\\n    __import__ | abs | all | any | ascii | bin | callable\\n    | chr | compile | copyright | credits | delattr | dir | divmod\\n    | enumerate | eval | exec | exit | filter | format | getattr\\n    | globals | hasattr | hash | help | hex | id | input\\n    | isinstance | issubclass | iter | len | license | locals | map\\n    | max | memoryview | min | next | oct | open | ord | pow | print\\n    | quit | range | reload | repr | reversed | round\\n    | setattr | sorted | sum | vars | zip\\n  )\\\\b\\n\"\n                },\n                {\n                    \"name\": \"variable.legacy.builtin.python\",\n                    \"match\":\n                        \"(?x)\\n  (?<!\\\\.) \\\\b(\\n    file | reduce | intern | raw_input | unicode | cmp | basestring\\n    | execfile | long | xrange\\n  )\\\\b\\n\"\n                }\n            ]\n        },\n        \"builtin-types\": {\n            \"name\": \"support.type.python\",\n            \"match\":\n                \"(?x)\\n  (?<!\\\\.) \\\\b(\\n    bool | bytearray | bytes | classmethod | complex | dict\\n    | float | frozenset | int | list | object | property\\n    | set | slice | staticmethod | str | tuple | type\\n\\n    (?# Although 'super' is not a type, it's related to types,\\n        and is special enough to be highlighted differently from\\n        other built-ins)\\n    | super\\n  )\\\\b\\n\"\n        },\n        \"magic-function-names\": {\n            \"comment\":\n                \"these methods have magic interpretation by python and are generally called\\nindirectly through syntactic constructs\\n\",\n            \"match\":\n                \"(?x)\\n  \\\\b(\\n    __(?:\\n      abs | add | aenter | aexit | aiter | and | anext | await\\n      | bool | call | ceil | cmp | coerce | complex | contains\\n      | copy | deepcopy | del | delattr | delete | delitem\\n      | delslice | dir | div | divmod | enter | eq | exit | float\\n      | floor | floordiv | format | ge | get | getattr\\n      | getattribute | getinitargs | getitem | getnewargs\\n      | getslice | getstate | gt | hash | hex | iadd | iand | idiv\\n      | ifloordiv | ilshift | imod | imul | index | init\\n      | instancecheck | int | invert | ior | ipow | irshift | isub\\n      | iter | itruediv | ixor | le | len | long | lshift | lt\\n      | missing | mod | mul | ne | neg | new | next | nonzero | oct | or\\n      | pos | pow | radd | rand | rdiv | rdivmod | reduce\\n      | reduce_ex | repr | reversed | rfloordiv | rlshift | rmod\\n      | rmul | ror | round | rpow | rrshift | rshift | rsub\\n      | rtruediv | rxor | set | setattr | setitem | setslice\\n      | setstate | sizeof | str | sub | subclasscheck | truediv\\n      | trunc | unicode | xor | matmul | rmatmul | imatmul\\n      | init_subclass | set_name | fspath | bytes | prepare\\n    )__\\n  )\\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"support.function.magic.python\"\n                }\n            }\n        },\n        \"magic-variable-names\": {\n            \"comment\": \"magic variables which a class/module may have.\",\n            \"match\":\n                \"(?x)\\n  \\\\b(\\n    __(?:\\n      all | bases | builtins | class | code | debug | defaults | dict\\n      | doc | file | func | kwdefaults | members\\n      | metaclass | methods | module | mro | name\\n      | qualname | self | signature | slots | subclasses\\n      | version | weakref | wrapped | annotations | classcell\\n      | spec | path | package | future | traceback\\n    )__\\n  )\\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"support.variable.magic.python\"\n                }\n            }\n        },\n        \"magic-names\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#magic-function-names\"\n                },\n                {\n                    \"include\": \"#magic-variable-names\"\n                }\n            ]\n        },\n        \"illegal-names\": {\n            \"name\": \"keyword.control.flow.python\",\n            \"match\":\n                \"(?x)\\n  \\\\b(\\n    and | as | assert | async | await | break | class | continue | def\\n    | del | elif | else | except | exec | finally | for | from | global\\n    | if | import | in | is | (?<=\\\\.)lambda | lambda(?=\\\\s*[\\\\.=])\\n    | nonlocal | not | or | pass | raise | return | try | while | with\\n    | yield\\n  )\\\\b\\n\"\n        },\n        \"special-variables\": {\n            \"match\": \"(?x)\\n  \\\\b (?<!\\\\.) (?:\\n    (self) | (cls)\\n  )\\\\b\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"variable.language.special.self.python\"\n                },\n                \"2\": {\n                    \"name\": \"variable.language.special.cls.python\"\n                }\n            }\n        },\n        \"ellipsis\": {\n            \"name\": \"constant.other.ellipsis.python\",\n            \"match\": \"\\\\.\\\\.\\\\.\"\n        },\n        \"backticks\": {\n            \"name\": \"invalid.deprecated.backtick.python\",\n            \"begin\": \"\\\\`\",\n            \"end\": \"(?:\\\\`|(?<!\\\\\\\\)(\\\\n))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"illegal-operator\": {\n            \"patterns\": [\n                {\n                    \"name\": \"invalid.illegal.operator.python\",\n                    \"match\": \"&&|\\\\|\\\\||--|\\\\+\\\\+\"\n                },\n                {\n                    \"name\": \"invalid.illegal.operator.python\",\n                    \"match\": \"[?$]\"\n                },\n                {\n                    \"name\": \"invalid.illegal.operator.python\",\n                    \"comment\": \"We don't want `!` to flash when we're typing `!=`\",\n                    \"match\": \"!\\\\b\"\n                }\n            ]\n        },\n        \"illegal-object-name\": {\n            \"comment\": \"It's illegal to name class or function \\\"True\\\"\",\n            \"name\": \"keyword.illegal.name.python\",\n            \"match\": \"\\\\b(True|False|None)\\\\b\"\n        },\n        \"illegal-anno\": {\n            \"name\": \"invalid.illegal.annotation.python\",\n            \"match\": \"->\"\n        },\n        \"regexp-base-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-quantifier\"\n                },\n                {\n                    \"include\": \"#regexp-base-common\"\n                }\n            ]\n        },\n        \"fregexp-base-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#fregexp-quantifier\"\n                },\n                {\n                    \"include\": \"#fstring-formatting-braces\"\n                },\n                {\n                    \"match\": \"\\\\{.*?\\\\}\"\n                },\n                {\n                    \"include\": \"#regexp-base-common\"\n                }\n            ]\n        },\n        \"fstring-formatting-braces\": {\n            \"patterns\": [\n                {\n                    \"comment\": \"empty braces are illegal\",\n                    \"match\": \"({)(\\\\s*?)(})\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"constant.character.format.placeholder.other.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.brace.python\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.character.format.placeholder.other.python\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"constant.character.escape.python\",\n                    \"match\": \"({{|}})\"\n                }\n            ]\n        },\n        \"regexp-base-common\": {\n            \"patterns\": [\n                {\n                    \"name\": \"support.other.match.any.regexp\",\n                    \"match\": \"\\\\.\"\n                },\n                {\n                    \"name\": \"support.other.match.begin.regexp\",\n                    \"match\": \"\\\\^\"\n                },\n                {\n                    \"name\": \"support.other.match.end.regexp\",\n                    \"match\": \"\\\\$\"\n                },\n                {\n                    \"name\": \"keyword.operator.quantifier.regexp\",\n                    \"match\": \"[+*?]\\\\??\"\n                },\n                {\n                    \"name\": \"keyword.operator.disjunction.regexp\",\n                    \"match\": \"\\\\|\"\n                },\n                {\n                    \"include\": \"#regexp-escape-sequence\"\n                }\n            ]\n        },\n        \"regexp-quantifier\": {\n            \"name\": \"keyword.operator.quantifier.regexp\",\n            \"match\": \"(?x)\\n  \\\\{(\\n    \\\\d+ | \\\\d+,(\\\\d+)? | ,\\\\d+\\n  )\\\\}\\n\"\n        },\n        \"fregexp-quantifier\": {\n            \"name\": \"keyword.operator.quantifier.regexp\",\n            \"match\": \"(?x)\\n  \\\\{\\\\{(\\n    \\\\d+ | \\\\d+,(\\\\d+)? | ,\\\\d+\\n  )\\\\}\\\\}\\n\"\n        },\n        \"regexp-backreference-number\": {\n            \"name\": \"meta.backreference.regexp\",\n            \"match\": \"(\\\\\\\\[1-9]\\\\d?)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.tag.backreference.regexp\"\n                }\n            }\n        },\n        \"regexp-backreference\": {\n            \"name\": \"meta.backreference.named.regexp\",\n            \"match\": \"(?x)\\n  (\\\\()  (\\\\?P= \\\\w+(?:\\\\s+[[:alnum:]]+)?)  (\\\\))\\n\",\n            \"captures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.backreference.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.backreference.regexp\"\n                },\n                \"3\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.backreference.named.end.regexp\"\n                }\n            }\n        },\n        \"regexp-flags\": {\n            \"name\": \"storage.modifier.flag.regexp\",\n            \"match\": \"\\\\(\\\\?[aiLmsux]+\\\\)\"\n        },\n        \"regexp-escape-special\": {\n            \"name\": \"support.other.escape.special.regexp\",\n            \"match\": \"\\\\\\\\([AbBdDsSwWZ])\"\n        },\n        \"regexp-escape-character\": {\n            \"name\": \"constant.character.escape.regexp\",\n            \"match\":\n                \"(?x)\\n  \\\\\\\\ (\\n        x[0-9A-Fa-f]{2}\\n        | 0[0-7]{1,2}\\n        | [0-7]{3}\\n     )\\n\"\n        },\n        \"regexp-escape-unicode\": {\n            \"name\": \"constant.character.unicode.regexp\",\n            \"match\": \"(?x)\\n  \\\\\\\\ (\\n        u[0-9A-Fa-f]{4}\\n        | U[0-9A-Fa-f]{8}\\n     )\\n\"\n        },\n        \"regexp-escape-catchall\": {\n            \"name\": \"constant.character.escape.regexp\",\n            \"match\": \"\\\\\\\\(.|\\\\n)\"\n        },\n        \"regexp-escape-sequence\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-escape-special\"\n                },\n                {\n                    \"include\": \"#regexp-escape-character\"\n                },\n                {\n                    \"include\": \"#regexp-escape-unicode\"\n                },\n                {\n                    \"include\": \"#regexp-backreference-number\"\n                },\n                {\n                    \"include\": \"#regexp-escape-catchall\"\n                }\n            ]\n        },\n        \"regexp-charecter-set-escapes\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.escape.regexp\",\n                    \"match\": \"\\\\\\\\[abfnrtv\\\\\\\\]\"\n                },\n                {\n                    \"include\": \"#regexp-escape-special\"\n                },\n                {\n                    \"name\": \"constant.character.escape.regexp\",\n                    \"match\": \"\\\\\\\\([0-7]{1,3})\"\n                },\n                {\n                    \"include\": \"#regexp-escape-character\"\n                },\n                {\n                    \"include\": \"#regexp-escape-unicode\"\n                },\n                {\n                    \"include\": \"#regexp-escape-catchall\"\n                }\n            ]\n        },\n        \"codetags\": {\n            \"match\": \"(?:\\\\b(NOTE|XXX|HACK|FIXME|BUG|TODO)\\\\b)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.codetag.notation.python\"\n                }\n            }\n        },\n        \"comments-base\": {\n            \"name\": \"comment.line.number-sign.python\",\n            \"begin\": \"(\\\\#)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.python\"\n                }\n            },\n            \"end\": \"($)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"comments-string-single-three\": {\n            \"name\": \"comment.line.number-sign.python\",\n            \"begin\": \"(\\\\#)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.python\"\n                }\n            },\n            \"end\": \"($|(?='''))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"comments-string-double-three\": {\n            \"name\": \"comment.line.number-sign.python\",\n            \"begin\": \"(\\\\#)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.python\"\n                }\n            },\n            \"end\": \"($|(?=\\\"\\\"\\\"))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"single-one-regexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-base-expression\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-lookahead\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-conditional\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-parentheses\"\n                }\n            ]\n        },\n        \"single-one-regexp-character-set\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n  \\\\[ \\\\^? \\\\] (?! .*?\\\\])\\n\"\n                },\n                {\n                    \"name\": \"meta.character.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?(\\\\])?\",\n                    \"end\": \"(\\\\]|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"punctuation.character.set.begin.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.character.set.regexp\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.character.set.end.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.newline.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp-charecter-set-escapes\"\n                        },\n                        {\n                            \"name\": \"constant.character.set.regexp\",\n                            \"match\": \"[^\\\\n]\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"single-one-regexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-comments\": {\n            \"name\": \"comment.regexp\",\n            \"begin\": \"\\\\(\\\\?#\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.comment.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.comment.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"single-one-regexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-regexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"single-three-regexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-base-expression\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-lookahead\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-conditional\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-parentheses\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-character-set\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n  \\\\[ \\\\^? \\\\] (?! .*?\\\\])\\n\"\n                },\n                {\n                    \"name\": \"meta.character.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?(\\\\])?\",\n                    \"end\": \"(\\\\]|(?=\\\\'\\\\'\\\\'))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"punctuation.character.set.begin.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.character.set.regexp\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.character.set.end.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.newline.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp-charecter-set-escapes\"\n                        },\n                        {\n                            \"name\": \"constant.character.set.regexp\",\n                            \"match\": \"[^\\\\n]\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"single-three-regexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-comments\": {\n            \"name\": \"comment.regexp\",\n            \"begin\": \"\\\\(\\\\?#\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.comment.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.comment.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"single-three-regexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-regexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"double-one-regexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-base-expression\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-lookahead\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-conditional\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-parentheses\"\n                }\n            ]\n        },\n        \"double-one-regexp-character-set\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n  \\\\[ \\\\^? \\\\] (?! .*?\\\\])\\n\"\n                },\n                {\n                    \"name\": \"meta.character.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?(\\\\])?\",\n                    \"end\": \"(\\\\]|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"punctuation.character.set.begin.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.character.set.regexp\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.character.set.end.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.newline.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp-charecter-set-escapes\"\n                        },\n                        {\n                            \"name\": \"constant.character.set.regexp\",\n                            \"match\": \"[^\\\\n]\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"double-one-regexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-comments\": {\n            \"name\": \"comment.regexp\",\n            \"begin\": \"\\\\(\\\\?#\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.comment.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.comment.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"double-one-regexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-one-regexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"double-three-regexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#regexp-base-expression\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-lookahead\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-conditional\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-parentheses\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-character-set\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n  \\\\[ \\\\^? \\\\] (?! .*?\\\\])\\n\"\n                },\n                {\n                    \"name\": \"meta.character.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?(\\\\])?\",\n                    \"end\": \"(\\\\]|(?=\\\"\\\"\\\"))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"punctuation.character.set.begin.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.character.set.regexp\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.character.set.end.regexp constant.other.set.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"invalid.illegal.newline.python\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp-charecter-set-escapes\"\n                        },\n                        {\n                            \"name\": \"constant.character.set.regexp\",\n                            \"match\": \"[^\\\\n]\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"double-three-regexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-comments\": {\n            \"name\": \"comment.regexp\",\n            \"begin\": \"\\\\(\\\\?#\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.comment.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.comment.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#codetags\"\n                }\n            ]\n        },\n        \"double-three-regexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-regexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"regexp-single-one-line\": {\n            \"name\": \"string.regexp.quoted.single.python\",\n            \"begin\": \"\\\\b(([uU]r)|([bB]r)|(r[bB]?))(\\\\')\",\n            \"end\": \"(\\\\')|(?<!\\\\\\\\)(\\\\n)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-regexp-expression\"\n                }\n            ]\n        },\n        \"regexp-single-three-line\": {\n            \"name\": \"string.regexp.quoted.multi.python\",\n            \"begin\": \"\\\\b(([uU]r)|([bB]r)|(r[bB]?))(\\\\'\\\\'\\\\')\",\n            \"end\": \"(\\\\'\\\\'\\\\')\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-regexp-expression\"\n                }\n            ]\n        },\n        \"regexp-double-one-line\": {\n            \"name\": \"string.regexp.quoted.single.python\",\n            \"begin\": \"\\\\b(([uU]r)|([bB]r)|(r[bB]?))(\\\")\",\n            \"end\": \"(\\\")|(?<!\\\\\\\\)(\\\\n)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-regexp-expression\"\n                }\n            ]\n        },\n        \"regexp-double-three-line\": {\n            \"name\": \"string.regexp.quoted.multi.python\",\n            \"begin\": \"\\\\b(([uU]r)|([bB]r)|(r[bB]?))(\\\"\\\"\\\")\",\n            \"end\": \"(\\\"\\\"\\\")\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-regexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#fregexp-base-expression\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#single-one-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-lookahead\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-conditional\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#single-one-fregexp-parentheses\"\n                }\n            ]\n        },\n        \"single-one-fregexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-one-fregexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\\'))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"single-three-fregexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#fregexp-base-expression\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#single-three-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-lookahead\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-conditional\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#single-three-fregexp-parentheses\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"single-three-fregexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\\'\\\\'\\\\'))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-single-three\"\n                }\n            ]\n        },\n        \"double-one-fregexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#fregexp-base-expression\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#double-one-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-lookahead\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-conditional\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#double-one-fregexp-parentheses\"\n                }\n            ]\n        },\n        \"double-one-fregexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-one-fregexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\"))|((?=(?<!\\\\\\\\)\\\\n))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"double-three-fregexp-expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#fregexp-base-expression\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-character-set\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-comments\"\n                },\n                {\n                    \"include\": \"#regexp-flags\"\n                },\n                {\n                    \"include\": \"#double-three-regexp-named-group\"\n                },\n                {\n                    \"include\": \"#regexp-backreference\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-lookahead\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-lookahead-negative\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-lookbehind\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-lookbehind-negative\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-conditional\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-parentheses-non-capturing\"\n                },\n                {\n                    \"include\": \"#double-three-fregexp-parentheses\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-named-group\": {\n            \"name\": \"meta.named.regexp\",\n            \"begin\": \"(?x)\\n  (\\\\()  (\\\\?P <\\\\w+(?:\\\\s+[[:alnum:]]+)?>)\\n\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.begin.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.named.group.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.named.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-lookahead\": {\n            \"begin\": \"(\\\\()\\\\?=\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-lookahead-negative\": {\n            \"begin\": \"(\\\\()\\\\?!\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookahead.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookahead.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookahead.negative.regexp punctuation.parenthesis.lookahead.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-lookbehind\": {\n            \"begin\": \"(\\\\()\\\\?<=\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-lookbehind-negative\": {\n            \"begin\": \"(\\\\()\\\\?<!\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.lookbehind.negative.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.lookbehind.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.lookbehind.negative.regexp punctuation.parenthesis.lookbehind.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-conditional\": {\n            \"begin\": \"(\\\\()\\\\?\\\\((\\\\w+(?:\\\\s+[[:alnum:]]+)?|\\\\d+)\\\\)\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.conditional.regexp\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.parenthesis.conditional.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"keyword.operator.conditional.negative.regexp punctuation.parenthesis.conditional.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-parentheses-non-capturing\": {\n            \"begin\": \"\\\\(\\\\?:\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"support.other.parenthesis.regexp punctuation.parenthesis.non-capturing.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"double-three-fregexp-parentheses\": {\n            \"begin\": \"\\\\(\",\n            \"end\": \"(\\\\)|(?=\\\"\\\"\\\"))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"support.other.parenthesis.regexp punctuation.parenthesis.end.regexp\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                },\n                {\n                    \"include\": \"#comments-string-double-three\"\n                }\n            ]\n        },\n        \"fregexp-single-one-line\": {\n            \"name\": \"string.interpolated.python string.regexp.quoted.single.python\",\n            \"begin\": \"\\\\b(([uU]r)|([fF]r)|(r[fF]?))(\\\\')\",\n            \"end\": \"(\\\\')|(?<!\\\\\\\\)(\\\\n)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"fregexp-single-three-line\": {\n            \"name\": \"string.interpolated.python string.regexp.quoted.multi.python\",\n            \"begin\": \"\\\\b(([uU]r)|([fF]r)|(r[fF]?))(\\\\'\\\\'\\\\')\",\n            \"end\": \"(\\\\'\\\\'\\\\')\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#single-three-fregexp-expression\"\n                }\n            ]\n        },\n        \"fregexp-double-one-line\": {\n            \"name\": \"string.interpolated.python string.regexp.quoted.single.python\",\n            \"begin\": \"\\\\b(([uU]r)|([fF]r)|(r[fF]?))(\\\")\",\n            \"end\": \"(\\\")|(?<!\\\\\\\\)(\\\\n)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-one-fregexp-expression\"\n                }\n            ]\n        },\n        \"fregexp-double-three-line\": {\n            \"name\": \"string.interpolated.python string.regexp.quoted.multi.python\",\n            \"begin\": \"\\\\b(([uU]r)|([fF]r)|(r[fF]?))(\\\"\\\"\\\")\",\n            \"end\": \"(\\\"\\\"\\\")\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#double-three-fregexp-expression\"\n                }\n            ]\n        },\n        \"string-raw-quoted-single-line\": {\n            \"name\": \"string.quoted.raw.single.python\",\n            \"begin\": \"\\\\b(([uU]R)|(R))((['\\\"]))\",\n            \"end\": \"(\\\\4)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-single-bad-brace1-formatting-raw\"\n                },\n                {\n                    \"include\": \"#string-single-bad-brace2-formatting-raw\"\n                },\n                {\n                    \"include\": \"#string-raw-guts\"\n                }\n            ]\n        },\n        \"string-bin-quoted-single-line\": {\n            \"name\": \"string.quoted.binary.single.python\",\n            \"begin\": \"(\\\\b[bB])((['\\\"]))\",\n            \"end\": \"(\\\\2)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-entity\"\n                }\n            ]\n        },\n        \"string-raw-bin-quoted-single-line\": {\n            \"name\": \"string.quoted.raw.binary.single.python\",\n            \"begin\": \"(\\\\b(?:R[bB]|[bB]R))((['\\\"]))\",\n            \"end\": \"(\\\\2)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-raw-bin-guts\"\n                }\n            ]\n        },\n        \"string-quoted-single-line\": {\n            \"name\": \"string.quoted.single.python\",\n            \"begin\": \"(\\\\b[rR](?=[uU]))?([uU])?((['\\\"]))\",\n            \"end\": \"(\\\\3)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.prefix.python\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-single-bad-brace1-formatting-unicode\"\n                },\n                {\n                    \"include\": \"#string-single-bad-brace2-formatting-unicode\"\n                },\n                {\n                    \"include\": \"#string-unicode-guts\"\n                }\n            ]\n        },\n        \"string-single-bad-brace1-formatting-unicode\": {\n            \"comment\": \"template using {% ... %}\",\n            \"begin\":\n                \"(?x)\\n    (?= \\\\{%\\n          ( .*? (?!(['\\\"])|((?<!\\\\\\\\)\\\\n)) )\\n        %\\\\}\\n    )\\n\",\n            \"end\": \"(?=(['\\\"])|((?<!\\\\\\\\)\\\\n))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#escape-sequence\"\n                },\n                {\n                    \"include\": \"#string-line-continuation\"\n                }\n            ]\n        },\n        \"string-single-bad-brace1-formatting-raw\": {\n            \"comment\": \"template using {% ... %}\",\n            \"begin\":\n                \"(?x)\\n    (?= \\\\{%\\n          ( .*? (?!(['\\\"])|((?<!\\\\\\\\)\\\\n)) )\\n        %\\\\}\\n    )\\n\",\n            \"end\": \"(?=(['\\\"])|((?<!\\\\\\\\)\\\\n))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                }\n            ]\n        },\n        \"string-single-bad-brace2-formatting-unicode\": {\n            \"comment\": \"odd format or format-like syntax\",\n            \"begin\":\n                \"(?x)\\n    (?!\\\\{\\\\{)\\n    (?= \\\\{ (\\n              \\\\w*? (?!(['\\\"])|((?<!\\\\\\\\)\\\\n)) [^!:\\\\.\\\\[}\\\\w]\\n           )\\n        .*?(?!(['\\\"])|((?<!\\\\\\\\)\\\\n))\\n        \\\\}\\n    )\\n\",\n            \"end\": \"(?=(['\\\"])|((?<!\\\\\\\\)\\\\n))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#string-entity\"\n                }\n            ]\n        },\n        \"string-single-bad-brace2-formatting-raw\": {\n            \"comment\": \"odd format or format-like syntax\",\n            \"begin\":\n                \"(?x)\\n    (?!\\\\{\\\\{)\\n    (?= \\\\{ (\\n              \\\\w*? (?!(['\\\"])|((?<!\\\\\\\\)\\\\n)) [^!:\\\\.\\\\[}\\\\w]\\n           )\\n        .*?(?!(['\\\"])|((?<!\\\\\\\\)\\\\n))\\n        \\\\}\\n    )\\n\",\n            \"end\": \"(?=(['\\\"])|((?<!\\\\\\\\)\\\\n))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                },\n                {\n                    \"include\": \"#string-formatting\"\n                }\n            ]\n        },\n        \"string-raw-quoted-multi-line\": {\n            \"name\": \"string.quoted.raw.multi.python\",\n            \"begin\": \"\\\\b(([uU]R)|(R))('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\4)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"invalid.deprecated.prefix.python\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-multi-bad-brace1-formatting-raw\"\n                },\n                {\n                    \"include\": \"#string-multi-bad-brace2-formatting-raw\"\n                },\n                {\n                    \"include\": \"#string-raw-guts\"\n                }\n            ]\n        },\n        \"string-bin-quoted-multi-line\": {\n            \"name\": \"string.quoted.binary.multi.python\",\n            \"begin\": \"(\\\\b[bB])('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\2)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-entity\"\n                }\n            ]\n        },\n        \"string-raw-bin-quoted-multi-line\": {\n            \"name\": \"string.quoted.raw.binary.multi.python\",\n            \"begin\": \"(\\\\b(?:R[bB]|[bB]R))('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\2)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-raw-bin-guts\"\n                }\n            ]\n        },\n        \"string-quoted-multi-line\": {\n            \"name\": \"string.quoted.multi.python\",\n            \"begin\": \"(\\\\b[rR](?=[uU]))?([uU])?('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\3)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.prefix.python\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.string.python\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.string.begin.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-multi-bad-brace1-formatting-unicode\"\n                },\n                {\n                    \"include\": \"#string-multi-bad-brace2-formatting-unicode\"\n                },\n                {\n                    \"include\": \"#string-unicode-guts\"\n                }\n            ]\n        },\n        \"string-multi-bad-brace1-formatting-unicode\": {\n            \"comment\": \"template using {% ... %}\",\n            \"begin\": \"(?x)\\n    (?= \\\\{%\\n          ( .*? (?!'''|\\\"\\\"\\\") )\\n        %\\\\}\\n    )\\n\",\n            \"end\": \"(?='''|\\\"\\\"\\\")\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#escape-sequence\"\n                },\n                {\n                    \"include\": \"#string-line-continuation\"\n                }\n            ]\n        },\n        \"string-multi-bad-brace1-formatting-raw\": {\n            \"comment\": \"template using {% ... %}\",\n            \"begin\": \"(?x)\\n    (?= \\\\{%\\n          ( .*? (?!'''|\\\"\\\"\\\") )\\n        %\\\\}\\n    )\\n\",\n            \"end\": \"(?='''|\\\"\\\"\\\")\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                }\n            ]\n        },\n        \"string-multi-bad-brace2-formatting-unicode\": {\n            \"comment\": \"odd format or format-like syntax\",\n            \"begin\":\n                \"(?x)\\n    (?!\\\\{\\\\{)\\n    (?= \\\\{ (\\n              \\\\w*? (?!'''|\\\"\\\"\\\") [^!:\\\\.\\\\[}\\\\w]\\n           )\\n        .*?(?!'''|\\\"\\\"\\\")\\n        \\\\}\\n    )\\n\",\n            \"end\": \"(?='''|\\\"\\\"\\\")\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escape-sequence-unicode\"\n                },\n                {\n                    \"include\": \"#string-entity\"\n                }\n            ]\n        },\n        \"string-multi-bad-brace2-formatting-raw\": {\n            \"comment\": \"odd format or format-like syntax\",\n            \"begin\":\n                \"(?x)\\n    (?!\\\\{\\\\{)\\n    (?= \\\\{ (\\n              \\\\w*? (?!'''|\\\"\\\"\\\") [^!:\\\\.\\\\[}\\\\w]\\n           )\\n        .*?(?!'''|\\\"\\\"\\\")\\n        \\\\}\\n    )\\n\",\n            \"end\": \"(?='''|\\\"\\\"\\\")\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string-consume-escape\"\n                },\n                {\n                    \"include\": \"#string-formatting\"\n                }\n            ]\n        },\n        \"fstring-fnorm-quoted-single-line\": {\n            \"name\": \"meta.fstring.python\",\n            \"begin\": \"(\\\\b[fF])([bBuU])?((['\\\"]))\",\n            \"end\": \"(\\\\3)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"string.interpolated.python string.quoted.single.python storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.prefix.python\"\n                },\n                \"3\": {\n                    \"name\":\n                        \"punctuation.definition.string.begin.python string.interpolated.python string.quoted.single.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"punctuation.definition.string.end.python string.interpolated.python string.quoted.single.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-guts\"\n                },\n                {\n                    \"include\": \"#fstring-illegal-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-single-core\"\n                }\n            ]\n        },\n        \"fstring-normf-quoted-single-line\": {\n            \"name\": \"meta.fstring.python\",\n            \"begin\": \"(\\\\b[bBuU])([fF])((['\\\"]))\",\n            \"end\": \"(\\\\3)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.prefix.python\"\n                },\n                \"2\": {\n                    \"name\":\n                        \"string.interpolated.python string.quoted.single.python storage.type.string.python\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.string.begin.python string.quoted.single.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"punctuation.definition.string.end.python string.interpolated.python string.quoted.single.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-guts\"\n                },\n                {\n                    \"include\": \"#fstring-illegal-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-single-core\"\n                }\n            ]\n        },\n        \"fstring-raw-quoted-single-line\": {\n            \"name\": \"meta.fstring.python\",\n            \"begin\": \"(\\\\b(?:[R][fF]|[fF][R]))((['\\\"]))\",\n            \"end\": \"(\\\\2)|((?<!\\\\\\\\)\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"string.interpolated.python string.quoted.raw.single.python storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\":\n                        \"punctuation.definition.string.begin.python string.quoted.raw.single.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"punctuation.definition.string.end.python string.interpolated.python string.quoted.raw.single.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-raw-guts\"\n                },\n                {\n                    \"include\": \"#fstring-illegal-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-raw-single-core\"\n                }\n            ]\n        },\n        \"fstring-single-core\": {\n            \"name\": \"string.interpolated.python string.quoted.single.python\",\n            \"match\":\n                \"(?x)\\n  (.+?)\\n    (\\n      (?# .* and .*? in multi-line match need special handling of\\n        newlines otherwise SublimeText and Atom will match slightly\\n        differently.\\n\\n        The guard for newlines has to be separate from the\\n        lookahead because of special $ matching rule.)\\n      ($\\\\n?)\\n      |\\n      (?=[\\\\\\\\\\\\}\\\\{]|(['\\\"])|((?<!\\\\\\\\)\\\\n))\\n    )\\n  (?# due to how multiline regexps are matched we need a special case\\n    for matching a newline character)\\n  | \\\\n\\n\"\n        },\n        \"fstring-raw-single-core\": {\n            \"name\": \"string.interpolated.python string.quoted.raw.single.python\",\n            \"match\":\n                \"(?x)\\n  (.+?)\\n    (\\n      (?# .* and .*? in multi-line match need special handling of\\n        newlines otherwise SublimeText and Atom will match slightly\\n        differently.\\n\\n        The guard for newlines has to be separate from the\\n        lookahead because of special $ matching rule.)\\n      ($\\\\n?)\\n      |\\n      (?=[\\\\\\\\\\\\}\\\\{]|(['\\\"])|((?<!\\\\\\\\)\\\\n))\\n    )\\n  (?# due to how multiline regexps are matched we need a special case\\n    for matching a newline character)\\n  | \\\\n\\n\"\n        },\n        \"fstring-single-brace\": {\n            \"comment\": \"value interpolation using { ... }\",\n            \"begin\": \"(\\\\{)\",\n            \"end\": \"(?x)\\n  (\\\\})|(?=\\\\n)\\n\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"constant.character.format.placeholder.other.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"constant.character.format.placeholder.other.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-terminator-single\"\n                },\n                {\n                    \"include\": \"#f-expression\"\n                }\n            ]\n        },\n        \"fstring-terminator-single\": {\n            \"patterns\": [\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(![rsa])(?=})\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n  (![rsa])?\\n    ( : \\\\w? [<>=^]? [-+ ]? \\\\#?\\n      \\\\d* ,? (\\\\.\\\\d+)? [bcdeEfFgGnosxX%]? )(?=})\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.format.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.format.python\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#fstring-terminator-single-tail\"\n                }\n            ]\n        },\n        \"fstring-terminator-single-tail\": {\n            \"begin\": \"(![rsa])?(:)(?=.*?{)\",\n            \"end\": \"(?=})|(?=\\\\n)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.format.python\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.format.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-illegal-single-brace\"\n                },\n                {\n                    \"include\": \"#fstring-single-brace\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"([bcdeEfFgGnosxX%])(?=})\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\.\\\\d+)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(,)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\d+)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\#)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"([-+ ])\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"([<>=^])\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\w)\"\n                }\n            ]\n        },\n        \"fstring-fnorm-quoted-multi-line\": {\n            \"name\": \"meta.fstring.python\",\n            \"begin\": \"(\\\\b[fF])([bBuU])?('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\3)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"string.interpolated.python string.quoted.multi.python storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.prefix.python\"\n                },\n                \"3\": {\n                    \"name\":\n                        \"punctuation.definition.string.begin.python string.interpolated.python string.quoted.multi.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"punctuation.definition.string.end.python string.interpolated.python string.quoted.multi.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-guts\"\n                },\n                {\n                    \"include\": \"#fstring-illegal-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-multi-core\"\n                }\n            ]\n        },\n        \"fstring-normf-quoted-multi-line\": {\n            \"name\": \"meta.fstring.python\",\n            \"begin\": \"(\\\\b[bBuU])([fF])('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\3)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"invalid.illegal.prefix.python\"\n                },\n                \"2\": {\n                    \"name\":\n                        \"string.interpolated.python string.quoted.multi.python storage.type.string.python\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.string.begin.python string.quoted.multi.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"punctuation.definition.string.end.python string.interpolated.python string.quoted.multi.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-guts\"\n                },\n                {\n                    \"include\": \"#fstring-illegal-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-multi-core\"\n                }\n            ]\n        },\n        \"fstring-raw-quoted-multi-line\": {\n            \"name\": \"meta.fstring.python\",\n            \"begin\": \"(\\\\b(?:[R][fF]|[fF][R]))('''|\\\"\\\"\\\")\",\n            \"end\": \"(\\\\2)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"string.interpolated.python string.quoted.raw.multi.python storage.type.string.python\"\n                },\n                \"2\": {\n                    \"name\":\n                        \"punctuation.definition.string.begin.python string.quoted.raw.multi.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"punctuation.definition.string.end.python string.interpolated.python string.quoted.raw.multi.python\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-raw-guts\"\n                },\n                {\n                    \"include\": \"#fstring-illegal-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-raw-multi-core\"\n                }\n            ]\n        },\n        \"fstring-multi-core\": {\n            \"name\": \"string.interpolated.python string.quoted.multi.python\",\n            \"match\":\n                \"(?x)\\n  (.+?)\\n    (\\n      (?# .* and .*? in multi-line match need special handling of\\n        newlines otherwise SublimeText and Atom will match slightly\\n        differently.\\n\\n        The guard for newlines has to be separate from the\\n        lookahead because of special $ matching rule.)\\n      ($\\\\n?)\\n      |\\n      (?=[\\\\\\\\\\\\}\\\\{]|'''|\\\"\\\"\\\")\\n    )\\n  (?# due to how multiline regexps are matched we need a special case\\n    for matching a newline character)\\n  | \\\\n\\n\"\n        },\n        \"fstring-raw-multi-core\": {\n            \"name\": \"string.interpolated.python string.quoted.raw.multi.python\",\n            \"match\":\n                \"(?x)\\n  (.+?)\\n    (\\n      (?# .* and .*? in multi-line match need special handling of\\n        newlines otherwise SublimeText and Atom will match slightly\\n        differently.\\n\\n        The guard for newlines has to be separate from the\\n        lookahead because of special $ matching rule.)\\n      ($\\\\n?)\\n      |\\n      (?=[\\\\\\\\\\\\}\\\\{]|'''|\\\"\\\"\\\")\\n    )\\n  (?# due to how multiline regexps are matched we need a special case\\n    for matching a newline character)\\n  | \\\\n\\n\"\n        },\n        \"fstring-multi-brace\": {\n            \"comment\": \"value interpolation using { ... }\",\n            \"begin\": \"(\\\\{)\",\n            \"end\": \"(?x)\\n  (\\\\})\\n\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"constant.character.format.placeholder.other.python\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"constant.character.format.placeholder.other.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-terminator-multi\"\n                },\n                {\n                    \"include\": \"#f-expression\"\n                }\n            ]\n        },\n        \"fstring-terminator-multi\": {\n            \"patterns\": [\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(![rsa])(?=})\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n  (![rsa])?\\n    ( : \\\\w? [<>=^]? [-+ ]? \\\\#?\\n      \\\\d* ,? (\\\\.\\\\d+)? [bcdeEfFgGnosxX%]? )(?=})\\n\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.format.python\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.format.python\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#fstring-terminator-multi-tail\"\n                }\n            ]\n        },\n        \"fstring-terminator-multi-tail\": {\n            \"begin\": \"(![rsa])?(:)(?=.*?{)\",\n            \"end\": \"(?=})\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.format.python\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.format.python\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#fstring-illegal-multi-brace\"\n                },\n                {\n                    \"include\": \"#fstring-multi-brace\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"([bcdeEfFgGnosxX%])(?=})\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\.\\\\d+)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(,)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\d+)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\#)\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"([-+ ])\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"([<>=^])\"\n                },\n                {\n                    \"name\": \"storage.type.format.python\",\n                    \"match\": \"(\\\\w)\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/reason/README.md",
    "content": "Syntax and snippet files were pulled from this repository: https://github.com/reasonml-editor/vscode-reasonml\nLicense: https://github.com/reasonml-editor/vscode-reasonml/blob/master/LICENSE\n\nChanges should be committed to that repo, and pulled here.\n"
  },
  {
    "path": "extensions/reason/package.json",
    "content": "{\n    \"name\": \"Reason\",\n    \"version\": \"0.0.1\",\n    \"description\": \"Reason extension for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"snippets\": [\n            {\n                \"language\": \"reason\",\n                \"path\": \"snippets/reason.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/reason/snippets/reason.json",
    "content": "{\n    \"function\": {\n        \"prefix\": \"let\",\n        \"body\": [\"let ${1:f} = (${2:pattern}) => ${3:${2:pattern}};$0\"]\n    },\n    \"function (block)\": {\n        \"prefix\": \"let\",\n        \"body\": [\"let ${1:f} = (${2:pattern}) => {\", \"\\t${3:${2:pattern}}$0\", \"};\"]\n    },\n    \"lambda\": {\n        \"prefix\": \"fun\",\n        \"body\": [\"(${1:pattern}) => ${2:${1:pattern}}\"]\n    },\n    \"lambda (switch)\": {\n        \"prefix\": \"fun\",\n        \"body\": [\"fun\", \"\\t| ${1:pattern} => ${2:${1:pattern}}\", \"\\t;\"]\n    },\n    \"let\": {\n        \"prefix\": \"let\",\n        \"body\": [\"let ${1:pattern} = ${2:()};$0\"]\n    },\n    \"let (block)\": {\n        \"prefix\": \"let\",\n        \"body\": [\"let ${1:pattern} = {\", \"\\t$0\", \"};\"]\n    },\n    \"module\": {\n        \"prefix\": \"module\",\n        \"body\": [\"module ${1:M} = ${2:{}};$0\"]\n    },\n    \"module (block)\": {\n        \"prefix\": \"module\",\n        \"body\": [\"module ${1:M} = {\", \"\\t$0\", \"};\"]\n    },\n    \"module function\": {\n        \"prefix\": \"module\",\n        \"body\": [\"module ${1:M} = (${2:X}: $3{:{}}) => ${4:${2:X}};$0\"]\n    },\n    \"module function (block)\": {\n        \"prefix\": \"module\",\n        \"body\": [\"module ${1:M} = (${2:X}: $3{:{}}) => {\", \"\\t${4:include ${2:X}}\", \"\\t$0\", \"};\"]\n    },\n    \"switch\": {\n        \"prefix\": \"switch\",\n        \"body\": [\"switch ${1:scrutinee} {\", \"| ${2:pattern} => ${3:${2:pattern}}\", \"};\"]\n    },\n    \"type (alias or abstract)\": {\n        \"prefix\": \"type\",\n        \"body\": [\"type ${1:name} ${2:${3:'${4:arg} }= ${5:'${4:arg}}};$0\"]\n    },\n    \"type\": {\n        \"prefix\": \"type\",\n        \"body\": [\"type ${1:name} ${2:'${3:arg} }=\", \"\\t| ${4:Con${2: '${3:arg}}}\", \"\\t;\"]\n    }\n}\n"
  },
  {
    "path": "extensions/reason/syntaxes/reason.json",
    "content": "{\n    \"name\": \"Reason\",\n    \"scopeName\": \"source.reason\",\n    \"fileTypes\": [\"re\", \"rei\"],\n    \"patterns\": [\n        { \"include\": \"#structure-expression-block-item\" },\n        { \"include\": \"#value-expression\" }\n    ],\n    \"repository\": {\n        \"attribute\": {\n            \"begin\": \"(?=\\\\[(@{1,3})[[:space:]]*[[:alpha:]])\",\n            \"end\": \"\\\\]\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\[(@{1,3})\",\n                    \"end\": \"(?=[^_\\\\.'[:word:]])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#attribute-identifier\" }]\n                },\n                { \"include\": \"#attribute-payload\" }\n            ]\n        },\n        \"attribute-identifier\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b([[:alpha:]][[:word:]]*)\\\\b[[:space:]]*(?:(\\\\.))\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"support.class entity.name.class\" },\n                        \"2\": { \"name\": \"keyword.control.less\" }\n                    }\n                },\n                {\n                    \"match\": \"\\\\b([[:alpha:]][[:word:]]*)\\\\b\",\n                    \"name\": \"constant.language\"\n                }\n            ]\n        },\n        \"attribute-payload\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(:)\",\n                    \"end\": \"(?=\\\\])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#structure-expression\" },\n                        { \"include\": \"#module-item-type\" },\n                        { \"include\": \"#type-expression\" }\n                    ]\n                },\n                {\n                    \"begin\": \"([\\\\?])\",\n                    \"end\": \"(?=\\\\])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#pattern-guard\" }, { \"include\": \"#pattern\" }]\n                },\n                { \"include\": \"#structure-expression-block-item\" },\n                { \"include\": \"#value-expression\" }\n            ]\n        },\n        \"class-item-inherit\": {\n            \"begin\": \"\\\\b(inherit)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#value-expression\" }]\n        },\n        \"class-item-method\": {\n            \"begin\": \"\\\\b(method)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-let-value-bind-name-params-type-body\" }]\n        },\n        \"comment\": {\n            \"name\": \"comment\",\n            \"patterns\": [{ \"include\": \"#comment-block-doc\" }, { \"include\": \"#comment-block\" }]\n        },\n        \"comment-block\": {\n            \"begin\": \"/\\\\*\",\n            \"end\": \"\\\\*/\",\n            \"name\": \"comment.block\",\n            \"patterns\": [{ \"include\": \"#comment\" }]\n        },\n        \"comment-block-doc\": {\n            \"begin\": \"/\\\\*\\\\*(?!/)\",\n            \"end\": \"\\\\*/\",\n            \"name\": \"comment.block.documentation\",\n            \"patterns\": [{ \"include\": \"#comment\" }]\n        },\n        \"condition-lhs\": {\n            \"begin\": \"(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])([\\\\?])(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])\",\n            \"end\": \"(?=[\\\\)])\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control variable.interpolation\" }\n            },\n            \"patterns\": [\n                {\n                    \"match\": \"(?:\\\\b|[[:space:]]+)([?])(?:\\\\b|[[:space:]]+)\",\n                    \"name\": \"keyword.control variable.interpolation\"\n                },\n                { \"include\": \"#value-expression\" }\n            ]\n        },\n        \"extension-node\": {\n            \"begin\": \"(?=\\\\[(%{1,3})[[:space:]]*[[:alpha:]])\",\n            \"end\": \"\\\\]\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\[(%{1,3})\",\n                    \"end\": \"(?=[^_\\\\.'[:word:]])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#attribute-identifier\" }]\n                },\n                { \"include\": \"#attribute-payload\" }\n            ]\n        },\n        \"jsx\": {\n            \"patterns\": [{ \"include\": \"#jsx-head\" }, { \"include\": \"#jsx-tail\" }]\n        },\n        \"jsx-attributes\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b[[:space:]]*(=)\",\n                    \"end\": \"(?<![=])(?=[/>[:lower:]])\",\n                    \"comment\": \"meta.separator\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"entity.other.attribute-name\" },\n                        \"2\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#value-expression-atomic-with-paths\" }]\n                },\n                {\n                    \"match\": \"(\\\\b([[:lower:]][[:word:]]*)\\\\b[[:space:]]*+)\",\n                    \"captures\": {\n                        \"1\": { \"comment\": \"meta.separator\" },\n                        \"2\": { \"name\": \"entity.other.attribute-name\" }\n                    }\n                }\n            ]\n        },\n        \"jsx-body\": {\n            \"begin\": \"((>))\",\n            \"end\": \"(?=</)\",\n            \"beginCaptures\": {\n                \"1\": { \"comment\": \"meta.separator\" },\n                \"2\": { \"name\": \"punctuation.definition.tag.end.js\" }\n            },\n            \"patterns\": [\n                {\n                    \"comment\":\n                        \"FIXME: seems necessary in order to properly tokenize `[[:word:]]</` boundary\",\n                    \"match\": \"[[:lower:]][[:word:]]*\"\n                },\n                { \"include\": \"#value-expression\" }\n            ]\n        },\n        \"jsx-head\": {\n            \"begin\": \"((<))(?=[_[:alpha:]])\",\n            \"end\": \"((/>))|(?=</)\",\n            \"applyEndPatternLast\": true,\n            \"beginCaptures\": {\n                \"1\": { \"comment\": \"meta.separator\" },\n                \"2\": { \"name\": \"punctuation.definition.tag.begin.js\" }\n            },\n            \"endCaptures\": {\n                \"1\": { \"comment\": \"meta.separator\" },\n                \"2\": { \"name\": \"punctuation.definition.tag.end.js\" }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\G\",\n                    \"end\": \"(?=[[:space:]/>])[[:space:]]*+\",\n                    \"comment\": \"meta.separator\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n                            \"name\": \"entity.name.tag.inline.any.class\"\n                        },\n                        {\n                            \"match\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n                            \"name\": \"entity.name.tag.inline.any.html\"\n                        }\n                    ]\n                },\n                { \"include\": \"#jsx-attributes\" },\n                { \"include\": \"#jsx-body\" }\n            ]\n        },\n        \"jsx-tail\": {\n            \"begin\": \"\\\\G(/>)|(</)\",\n            \"end\": \"(>)\",\n            \"applyEndPatternLast\": true,\n            \"comment\": \"meta.separator\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"punctuation.definition.tag.end.js\" },\n                \"2\": { \"name\": \"punctuation.definition.tag.begin.js\" }\n            },\n            \"endCaptures\": {\n                \"1\": { \"name\": \"punctuation.definition.tag.end.js\" }\n            },\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n                    \"name\": \"entity.name.tag.inline.any.class\"\n                },\n                {\n                    \"match\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n                    \"name\": \"entity.name.tag.inline.any.html\"\n                }\n            ]\n        },\n        \"module-name-extended\": {\n            \"patterns\": [\n                { \"include\": \"#module-name-simple\" },\n                {\n                    \"begin\": \"([\\\\(])\",\n                    \"end\": \"([\\\\)])\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#module-path-extended\" }]\n                }\n            ]\n        },\n        \"module-name-simple\": {\n            \"match\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n            \"name\": \"support.class entity.name.class\"\n        },\n        \"module-path-extended\": {\n            \"patterns\": [\n                { \"include\": \"#module-name-extended\" },\n                { \"include\": \"#comment\" },\n                {\n                    \"comment\": \"NOTE: end early to avoid too much reparsing\",\n                    \"begin\": \"([\\\\.])\",\n                    \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?<=[\\\\.])\",\n                            \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n                            \"patterns\": [\n                                { \"include\": \"#comment\" },\n                                { \"include\": \"#module-name-extended\" }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"module-path-extended-prefix\": {\n            \"begin\": \"(?=\\\\b[[:upper:]])\",\n            \"end\":\n                \"([\\\\.])|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#module-path-extended\" }]\n        },\n        \"module-path-simple\": {\n            \"patterns\": [\n                { \"include\": \"#module-name-simple\" },\n                { \"include\": \"#comment\" },\n                {\n                    \"comment\": \"NOTE: end early to avoid too much reparsing\",\n                    \"begin\": \"([\\\\.])\",\n                    \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?<=[\\\\.])\",\n                            \"end\": \"(?<=[[:word:]\\\\)])|(?=[^\\\\.[:upper:]/])\",\n                            \"patterns\": [\n                                { \"include\": \"#comment\" },\n                                { \"include\": \"#module-name-simple\" }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"module-path-simple-prefix\": {\n            \"begin\": \"(?=\\\\b[[:upper:]])\",\n            \"end\":\n                \"([\\\\.])|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#module-path-simple\" }]\n        },\n        \"module-item-class-type\": {\n            \"comment\": \"FIXME: proper parsing\",\n            \"begin\": \"\\\\b(class)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(type)\\\\b\",\n                    \"end\": \"(?==)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#module-item-type-bind-name-tyvars\" }]\n                },\n                {\n                    \"begin\": \"(=)\",\n                    \"end\": \"(?=;)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#attribute\" },\n                        { \"include\": \"#comment\" },\n                        { \"include\": \"#class-item-inherit\" },\n                        { \"include\": \"#class-item-method\" }\n                    ]\n                }\n            ]\n        },\n        \"module-item-exception\": {\n            \"begin\": \"\\\\b(exception)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-type-bind-body-item\" }]\n        },\n        \"module-item-external\": {\n            \"begin\": \"\\\\b(external)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#module-item-let-value-bind-name-or-pattern\" },\n                { \"include\": \"#module-item-let-value-bind-type\" },\n                {\n                    \"begin\": \"(=)\",\n                    \"end\":\n                        \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#attribute\" },\n                        {\n                            \"begin\": \"\\\"\",\n                            \"end\": \"\\\"\",\n                            \"name\": \"string.double string.regexp\",\n                            \"patterns\": [\n                                { \"include\": \"#value-literal-string-escape\" },\n                                {\n                                    \"match\": \"(?:(%)(.*?)|(caml.*?))(?=\\\"|(?:[^\\\\\\\\\\\\n]$))\",\n                                    \"captures\": {\n                                        \"1\": { \"name\": \"constant.language\" },\n                                        \"2\": {\n                                            \"name\":\n                                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                        },\n                                        \"3\": {\n                                            \"name\":\n                                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                        }\n                                    }\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"module-item-include\": {\n            \"begin\": \"\\\\b(include)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.include\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#signature-expression\" }]\n        },\n        \"module-item-let\": {\n            \"begin\": \"\\\\b(let)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#module-item-let-module\" },\n                { \"include\": \"#module-item-let-value\" }\n            ]\n        },\n        \"module-item-let-module\": {\n            \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(module)\\\\b\",\n            \"end\":\n                \"(?=[;}]|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"variable.other.class.js variable.interpolation keyword.other\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-item-let-module-and\" },\n                { \"include\": \"#module-item-let-module-rec\" },\n                { \"include\": \"#module-item-let-module-bind-name-params-type-body\" }\n            ]\n        },\n        \"module-item-let-module-and\": {\n            \"begin\": \"\\\\b(and)\\\\b\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-let-module-bind-name-params-type-body\" }]\n        },\n        \"module-item-let-module-bind-body\": {\n            \"begin\": \"(=>?)\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.less\" }\n            },\n            \"patterns\": [{ \"include\": \"#structure-expression\" }]\n        },\n        \"module-item-let-module-bind-name-params\": {\n            \"begin\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b\",\n            \"end\":\n                \"(?=[;:}=]|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"support.class entity.name.class\" }\n            },\n            \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#module-item-let-module-param\" }]\n        },\n        \"module-item-let-module-bind-name-params-type-body\": {\n            \"begin\": \"(?:\\\\G|^)\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-item-let-module-bind-name-params\" },\n                { \"include\": \"#module-item-let-module-bind-type\" },\n                { \"include\": \"#module-item-let-module-bind-body\" }\n            ]\n        },\n        \"module-item-let-module-bind-type\": {\n            \"begin\": \"(:)\",\n            \"end\":\n                \"(?=[;}=]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#signature-expression\" }]\n        },\n        \"module-item-let-module-param\": {\n            \"begin\": \"(?=\\\\()\",\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\(\",\n                    \"end\": \"(?=[:])\",\n                    \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#module-name-simple\" }]\n                },\n                {\n                    \"begin\": \"(:)\",\n                    \"end\": \"(?=\\\\))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [{ \"include\": \"#signature-expression\" }]\n                }\n            ]\n        },\n        \"module-item-let-module-rec\": {\n            \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(rec)\\\\b\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control storage.modifier.rec\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-let-module-bind-name-params-type-body\" }]\n        },\n        \"module-item-let-value\": {\n            \"patterns\": [\n                { \"include\": \"#module-item-let-value-and\" },\n                { \"include\": \"#module-item-let-value-rec\" },\n                { \"include\": \"#module-item-let-value-bind-name-params-type-body\" }\n            ]\n        },\n        \"module-item-let-value-and\": {\n            \"begin\": \"\\\\b(and)\\\\b\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-let-value-bind-name-params-type-body\" }]\n        },\n        \"module-item-let-value-bind-body\": {\n            \"begin\": \"(=>?)\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.less\" }\n            },\n            \"patterns\": [{ \"include\": \"#value-expression\" }]\n        },\n        \"module-item-let-value-bind-name-or-pattern\": {\n            \"begin\":\n                \"(?<=[^[:word:]]and|^and|[^[:word:]]external|^external|[^[:word:]]let|^let|[^[:word:]]method|^method|[^[:word:]]rec|^rec)[[:space:]]*\",\n            \"end\":\n                \"(?<=[^[:space:]])|(?=[[:space:]]|[;:}=]|\\\\b(and|as|class|constraint|exception|external|for|include|inherit|let|method|module|nonrec|open|private|rec|switch|try|type|val|while|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"match\": \"\\\\b(?:([_][[:word:]]+)|([[:lower:]][[:word:]]*))\\\\b\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"comment\" },\n                        \"2\": { \"name\": \"entity.name.function\" }\n                    }\n                },\n                { \"include\": \"#module-item-let-value-bind-parens-params\" },\n                { \"include\": \"#pattern\" }\n            ]\n        },\n        \"module-item-let-value-bind-name-params-type-body\": {\n            \"begin\":\n                \"(?<=[^[:word:]]and|^and|[^[:word:]]external|^external|[^[:word:]]let|^let|[^[:word:]]method|^method|[^[:word:]]rec|^rec)\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                {\n                    \"comment\": \"FIXME; hack for punned arguments\",\n                    \"begin\": \"(::)\",\n                    \"end\": \"(?<=[[:space:]])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#pattern\" },\n                        {\n                            \"begin\": \"(=)\",\n                            \"end\": \"(\\\\?)|(?<=[^[:space:]=][[:space:]])(?=[[:space:]]*+[^\\\\.])\",\n                            \"beginCaptures\": {\n                                \"1\": { \"name\": \"markup.inserted keyword.control.less\" }\n                            },\n                            \"endCaptures\": {\n                                \"1\": { \"name\": \"storage.type\" }\n                            },\n                            \"patterns\": [{ \"include\": \"#value-expression-atomic-with-paths\" }]\n                        }\n                    ]\n                },\n                { \"include\": \"#module-item-let-value-bind-name-or-pattern\" },\n                { \"include\": \"#module-item-let-value-bind-params-type\" },\n                { \"include\": \"#module-item-let-value-bind-type\" },\n                { \"include\": \"#module-item-let-value-bind-body\" }\n            ]\n        },\n        \"module-item-let-value-bind-params-type\": {\n            \"begin\": \"(?=[^[:space:]:=])\",\n            \"end\":\n                \"(?=[;}=]|\\\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-item-let-value-param\" },\n                {\n                    \"begin\": \"(?<![:])(:)[[:space:]]*(?![[:space:]]*[:\\\\)])\",\n                    \"end\":\n                        \"(?=[;}=]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [{ \"include\": \"#type-expression-atomic\" }]\n                }\n            ]\n        },\n        \"module-item-let-value-bind-parens-params\": {\n            \"begin\": \"\\\\((?![\\\\)])\",\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                { \"include\": \"#operator\" },\n                { \"include\": \"#pattern-parens-lhs\" },\n                { \"include\": \"#type-annotation-rhs\" },\n                { \"include\": \"#pattern\" }\n            ]\n        },\n        \"module-item-let-value-bind-pattern\": {\n            \"begin\":\n                \"(?<=[^[:word:]]and|^and|[^[:word:]]external|^external|[^[:word:]]let|^let|[^[:word:]]method|^method|[^[:word:]]rec|^rec)\",\n            \"end\":\n                \"(?=[;:}=]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-item-let-value-bind-parens-params\" },\n                { \"include\": \"#pattern\" }\n            ]\n        },\n        \"module-item-let-value-bind-type\": {\n            \"comment\": \"FIXME: lookahead\",\n            \"begin\": \"(?<![:])(:)(?![[:space:]]*[:\\\\)])\",\n            \"end\":\n                \"(?==[^>]|[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(type)\\\\b\",\n                    \"end\": \"([\\\\.])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    },\n                    \"endCaptures\": {\n                        \"1\": { \"name\": \"entity.name.function\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#pattern-variable\" }]\n                },\n                { \"include\": \"#type-expression\" }\n            ]\n        },\n        \"module-item-let-value-param\": {\n            \"patterns\": [\n                { \"include\": \"#module-item-let-value-param-label\" },\n                { \"include\": \"#module-item-let-value-param-type\" },\n                { \"include\": \"#module-item-let-value-param-module\" },\n                { \"include\": \"#pattern\" }\n            ]\n        },\n        \"module-item-let-value-param-label\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(\\\\b[[:lower:]][[:word:]]*\\\\b)?[[:space:]]*(::)\",\n                    \"end\": \"(?<=[[:space:]])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"markup.inserted constant.language support.property-value entity.name.filename\"\n                        },\n                        \"2\": { \"name\": \"keyword.control\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#pattern\" },\n                        {\n                            \"begin\": \"(=)\",\n                            \"end\": \"(\\\\?)|(?<=[^[:space:]=][[:space:]])(?=[[:space:]]*+[^\\\\.])\",\n                            \"beginCaptures\": {\n                                \"1\": { \"name\": \"markup.inserted keyword.control.less\" }\n                            },\n                            \"endCaptures\": {\n                                \"1\": { \"name\": \"storage.type\" }\n                            },\n                            \"patterns\": [{ \"include\": \"#value-expression-atomic-with-paths\" }]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"module-item-let-value-param-module\": {\n            \"comment\": \"FIXME: merge with pattern-parens\",\n            \"begin\": \"\\\\([[:space:]]*(?=\\\\b(module)\\\\b)\",\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(module)\\\\b\",\n                    \"end\": \"(?=\\\\))\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.other\" }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n                            \"name\": \"support.class entity.name.class\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"module-item-let-value-param-type\": {\n            \"comment\": \"FIXME: merge with pattern-parens\",\n            \"begin\": \"\\\\((?=\\\\b(type)\\\\b)\",\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(type)\\\\b\",\n                    \"end\": \"(?=\\\\))\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#pattern-variable\" }]\n                }\n            ]\n        },\n        \"module-item-let-value-rec\": {\n            \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(rec)\\\\b\",\n            \"end\":\n                \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control storage.modifier\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-let-value-bind-name-params-type-body\" }]\n        },\n        \"module-item-module\": {\n            \"comment\": \"NOTE: this is to support the let-module case without the let prefix\",\n            \"begin\": \"\\\\b(module)\\\\b[[:space:]]*(?!\\\\b(type)\\\\b|$)\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#module-item-let-module-and\" },\n                { \"include\": \"#module-item-let-module-rec\" },\n                { \"include\": \"#module-item-let-module-bind-name-params-type-body\" }\n            ]\n        },\n        \"module-item-module-type\": {\n            \"begin\": \"\\\\b(module)\\\\b[[:space:]]*(?=\\\\b(type)\\\\b|$)\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(type)\\\\b\",\n                    \"end\": \"(?==)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        {\n                            \"match\": \"([[:upper:]][[:word:]]*)\",\n                            \"captures\": {\n                                \"1\": { \"name\": \"support.class entity.name.class\" }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(=)\",\n                    \"end\": \"(?=;)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#signature-expression\" }]\n                }\n            ]\n        },\n        \"module-item-open\": {\n            \"begin\": \"\\\\b(open)\\\\b\",\n            \"end\":\n                \"(;)|(?=}|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.open\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#module-path-simple\" }]\n        },\n        \"module-item-type\": {\n            \"comment\":\n                \"FIXME: the semi-colon is optional so we can re-use this for hover, which does not print the trailing ;\",\n            \"begin\": \"\\\\b(type)\\\\b\",\n            \"end\":\n                \"(;)|(?=[\\\\)}]|\\\\b(class|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#module-item-type-and\" },\n                { \"include\": \"#module-item-type-constraint\" },\n                { \"include\": \"#module-item-type-bind\" }\n            ]\n        },\n        \"module-item-type-and\": {\n            \"comment\": \"FIXME: the optional `type` is for module constraints\",\n            \"begin\": \"\\\\b(and)\\\\b([[:space:]]*type)?\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(class|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" },\n                \"2\": { \"name\": \"constant.language\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-type-bind-name-tyvars-body\" }]\n        },\n        \"module-item-type-bind\": {\n            \"comment\": \"FIXME: only allow module paths before type variables\",\n            \"patterns\": [\n                { \"include\": \"#module-item-type-bind-nonrec\" },\n                { \"include\": \"#module-item-type-bind-name-tyvars-body\" }\n            ]\n        },\n        \"module-item-type-bind-body\": {\n            \"comment\": \"FIXME: parsing\",\n            \"begin\": \"(\\\\+?=)\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.less\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-type-bind-body-item\" }]\n        },\n        \"module-item-type-bind-body-item\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(=)(?!>)|\\\\b(private)\\\\b\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" },\n                        \"2\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation storage.modifier\"\n                        }\n                    }\n                },\n                {\n                    \"comment\": \"FIXME: specialized version of variant rule that also scans for (\",\n                    \"match\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b(?![[:space:]]*[\\\\.\\\\(])\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    }\n                },\n                {\n                    \"begin\": \"(\\\\.\\\\.)\",\n                    \"end\":\n                        \"(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    }\n                },\n                {\n                    \"begin\": \"(\\\\|)(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])[[:space:]]*\",\n                    \"end\":\n                        \"(?=[;\\\\)}]|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#value-expression-constructor\" },\n                        {\n                            \"match\": \"([:])|\\\\b(of)\\\\b\",\n                            \"captures\": {\n                                \"1\": { \"name\": \"keyword.control.less\" },\n                                \"2\": { \"name\": \"keyword.other\" }\n                            }\n                        },\n                        { \"include\": \"#type-expression\" }\n                    ]\n                },\n                {\n                    \"comment\": \"FIXME: remove this once the pretty printer no longer outputs 'of'\",\n                    \"match\": \"(:)|(\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|\\\\b(of)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"2\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"3\": { \"name\": \"keyword.other\" }\n                    }\n                },\n                { \"include\": \"#type-expression\" }\n            ]\n        },\n        \"module-item-type-bind-name-tyvars\": {\n            \"begin\": \"(?<=\\\\G|^|\\\\.)[[:space:]]*\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n            \"end\":\n                \"(?=\\\\+?=|[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"entity.name.function\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#attribute\" },\n                {\n                    \"match\": \"_\",\n                    \"name\": \"comment\"\n                },\n                {\n                    \"comment\": \"FIXME: add separate type-variable rule\",\n                    \"match\": \"([+\\\\-])?(?:(_)|(')([[:lower:]][[:word:]]*)\\\\b)(?!\\\\.[[:upper:]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"2\": { \"name\": \"comment\" },\n                        \"3\": { \"name\": \"comment\" },\n                        \"4\": { \"name\": \"variable.parameter string.other.link variable.language\" }\n                    }\n                }\n            ]\n        },\n        \"module-item-type-bind-name-tyvars-body\": {\n            \"begin\": \"(?=(\\\\G|^)[[:space:]]*\\\\b[[:alpha:]])\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#module-item-type-bind-name-tyvars\" },\n                { \"include\": \"#module-item-type-bind-body\" }\n            ]\n        },\n        \"module-item-type-bind-nonrec\": {\n            \"begin\": \"(?:\\\\G|^)[[:space:]]*\\\\b(nonrec)\\\\b\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control storage.modifier\" }\n            },\n            \"patterns\": [{ \"include\": \"#module-item-type-bind-name-tyvars-body\" }]\n        },\n        \"module-item-type-constraint\": {\n            \"comment\": \"FIXME: proper parsing\",\n            \"begin\": \"\\\\b(constraint)\\\\b\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"variable.other.class.js variable.interpolation storage.modifier\" }\n            },\n            \"patterns\": [\n                {\n                    \"comment\": \"FIXME: add separate type-variable rule\",\n                    \"match\": \"([+\\\\-])?(')([_[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"2\": { \"name\": \"comment\" },\n                        \"3\": { \"name\": \"variable.parameter string.other.link variable.language\" }\n                    }\n                },\n                {\n                    \"match\": \"=\",\n                    \"name\": \"keyword.control.less\"\n                },\n                { \"include\": \"#type-expression\" }\n            ]\n        },\n        \"object-item\": {\n            \"begin\": \"\\\\G|(;)\",\n            \"end\":\n                \"(?=[;}]|\\\\b(class|constraint|exception|external|include|let|module|nonrec|open|private|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#class-item-method\" }]\n        },\n        \"operator\": {\n            \"patterns\": [{ \"include\": \"#operator-infix\" }, { \"include\": \"#operator-prefix\" }]\n        },\n        \"operator-infix\": {\n            \"patterns\": [\n                {\n                    \"match\": \";\",\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                },\n                { \"include\": \"#operator-infix-assign\" },\n                { \"include\": \"#operator-infix-builtin\" },\n                { \"include\": \"#operator-infix-custom\" },\n                { \"comment\": \"#operator-infix-custom-hash\" }\n            ]\n        },\n        \"operator-infix-assign\": {\n            \"match\": \"(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])(=)(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])\",\n            \"name\":\n                \"variable.other.class.js variable.interpolation keyword.operator keyword.control.less\"\n        },\n        \"operator-infix-builtin\": {\n            \"match\": \":=\",\n            \"name\":\n                \"variable.other.class.js variable.interpolation keyword.operator keyword.control.less\"\n        },\n        \"operator-infix-custom\": {\n            \"match\":\n                \"(?:(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])((<>))(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|([#\\\\-@*/&%^+<=>$\\\\\\\\][#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]*|[|][#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]+)\",\n            \"captures\": {\n                \"1\": { \"comment\": \"meta.separator\" },\n                \"2\": { \"name\": \"punctuation.definition.tag.begin.js\" },\n                \"3\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            }\n        },\n        \"operator-infix-custom-hash\": {\n            \"match\": \"#[\\\\-:!?.@*/&%^+<=>|~$]+\",\n            \"name\":\n                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n        },\n        \"operator-prefix\": {\n            \"patterns\": [\n                { \"include\": \"#operator-prefix-bang\" },\n                { \"include\": \"#operator-prefix-label-token\" }\n            ]\n        },\n        \"operator-prefix-bang\": {\n            \"match\": \"![\\\\-:!?.@*/&%^+<=>|~$]*\",\n            \"name\":\n                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n        },\n        \"operator-prefix-label-token\": {\n            \"match\": \"[?~][\\\\-:!?.@*/&%^+<=>|~$]+\",\n            \"name\":\n                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n        },\n        \"pattern\": {\n            \"patterns\": [\n                { \"include\": \"#attribute\" },\n                { \"include\": \"#comment\" },\n                { \"include\": \"#pattern-atomic\" },\n                {\n                    \"match\":\n                        \"[[:space:]]*+(?:(\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|\\\\b(as)\\\\b|(\\\\.\\\\.\\\\.?))[[:space:]]*+\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"2\": { \"name\": \"keyword.other\" },\n                        \"3\": { \"name\": \"keyword.control\" }\n                    }\n                }\n            ]\n        },\n        \"pattern-atomic\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(exception)\\\\b\",\n                    \"name\": \"keyword.other\"\n                },\n                { \"include\": \"#value-expression-literal\" },\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#pattern-list-or-array\" },\n                { \"include\": \"#pattern-record\" },\n                { \"include\": \"#pattern-variable\" },\n                { \"include\": \"#pattern-parens\" }\n            ]\n        },\n        \"pattern-guard\": {\n            \"begin\": \"\\\\b(when)\\\\b\",\n            \"end\": \"(?==>)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            },\n            \"patterns\": [{ \"include\": \"#value-expression\" }]\n        },\n        \"pattern-list-or-array\": {\n            \"begin\": \"(\\\\[\\\\|?)(?![@%])\",\n            \"end\": \"(\\\\|?\\\\])\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"constant.language\" }\n            },\n            \"endCaptures\": {\n                \"1\": { \"name\": \"constant.language\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#value-expression-literal-list-or-array-separator\" },\n                { \"include\": \"#pattern\" }\n            ]\n        },\n        \"pattern-parens\": {\n            \"begin\": \"(?=\\\\()\",\n            \"end\":\n                \"\\\\)|(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#pattern-parens-lhs\" },\n                { \"include\": \"#type-annotation-rhs\" }\n            ]\n        },\n        \"pattern-parens-lhs\": {\n            \"begin\": \"\\\\(|(,)\",\n            \"end\":\n                \"(?=(?:[,:\\\\)]))|(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#pattern\" }]\n        },\n        \"record-path\": {\n            \"begin\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n            \"end\": \"(?=[^[:space:]\\\\.])(?!/\\\\*)\",\n            \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#record-path-suffix\" }]\n        },\n        \"record-path-suffix\": {\n            \"begin\": \"(\\\\.)\",\n            \"end\":\n                \"(\\\\))|\\\\b([[:upper:]][[:word:]]*)\\\\b|\\\\b([[:lower:]][[:word:]]*)\\\\b|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": { \"name\": \"keyword.control\" },\n                \"2\": { \"name\": \"support.class entity.name.class\" },\n                \"3\": {\n                    \"name\":\n                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"begin\": \"([\\\\(])\",\n                    \"end\": \"(?=[\\\\)])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        {\n                            \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b(?=[^\\\\)]*([\\\\.]))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                                },\n                                \"2\": { \"name\": \"keyword.other\" }\n                            }\n                        },\n                        {\n                            \"match\": \"([\\\\.])\",\n                            \"name\": \"keyword.control.less\"\n                        },\n                        {\n                            \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b[[:space:]]*\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.parameter string.other.link variable.language\"\n                                }\n                            }\n                        },\n                        { \"include\": \"#value-expression\" }\n                    ]\n                }\n            ]\n        },\n        \"pattern-record\": {\n            \"begin\": \"{\",\n            \"end\": \"}\",\n            \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#pattern-record-item\" }]\n        },\n        \"pattern-record-field\": {\n            \"begin\": \"\\\\b([_][[:word:]]*)\\\\b|\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n            \"end\": \"(,)|(?=})\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"comment\" },\n                \"2\": {\n                    \"name\":\n                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"begin\": \"\\\\G(:)\",\n                    \"end\": \"(?=[,}])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [{ \"include\": \"#pattern\" }]\n                }\n            ]\n        },\n        \"pattern-record-item\": {\n            \"patterns\": [\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#pattern-record-field\" }\n            ]\n        },\n        \"pattern-variable\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(_(?:[[:lower:]][[:word:]]*)?)\\\\b(?!\\\\.[[:upper:]])\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"comment\" }\n                    }\n                },\n                {\n                    \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"variable.other\" }\n                    }\n                }\n            ]\n        },\n        \"signature-expression\": {\n            \"patterns\": [\n                {\n                    \"comment\": \"FIXME: scan for :upper: to disambiguate type/signature in hover\",\n                    \"begin\": \"(?=\\\\([[:space:]]*[[:upper:]][[:word:]]*[[:space:]]*:)\",\n                    \"end\": \"(?=[;])\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?=\\\\()\",\n                            \"end\": \"(?=[;]|=>)\",\n                            \"patterns\": [{ \"include\": \"#module-item-let-module-param\" }]\n                        },\n                        {\n                            \"begin\": \"(=>)\",\n                            \"end\": \"(?=[;\\\\(])\",\n                            \"beginCaptures\": {\n                                \"1\": { \"name\": \"markup.inserted keyword.control.less\" }\n                            },\n                            \"patterns\": [{ \"include\": \"#structure-expression\" }]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b(module)\\\\b[[:space:]]*\\\\b(type)\\\\b([[:space:]]*\\\\b(of)\\\\b)?\",\n                    \"end\":\n                        \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"markup.inserted keyword.other variable.other.readwrite.instance\"\n                        },\n                        \"2\": { \"name\": \"constant.language\" },\n                        \"3\": {\n                            \"name\":\n                                \"markup.inserted keyword.other variable.other.readwrite.instance\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        { \"include\": \"#module-path-simple\" },\n                        {\n                            \"match\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b\",\n                            \"name\": \"support.class entity.name.class\"\n                        }\n                    ]\n                },\n                { \"include\": \"#signature-expression-constraints\" },\n                { \"include\": \"#structure-expression\" }\n            ]\n        },\n        \"signature-expression-constraints\": {\n            \"begin\": \"(?=\\\\b(with))\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val)\\\\b)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(and|with)\\\\b\",\n                    \"end\":\n                        \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation storage.modifier\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        {\n                            \"comment\":\n                                \"FIXME: special version of #module-item-type with non-consuming `;`. Atom seems to need this to work.\",\n                            \"begin\": \"\\\\b(type)\\\\b\",\n                            \"end\":\n                                \"(?=[;\\\\)}]|\\\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\\\b)\",\n                            \"beginCaptures\": {\n                                \"1\": { \"name\": \"constant.language\" }\n                            },\n                            \"patterns\": [\n                                { \"include\": \"#module-item-type-and\" },\n                                { \"include\": \"#module-item-type-constraint\" },\n                                { \"include\": \"#module-item-type-bind\" }\n                            ]\n                        },\n                        {\n                            \"begin\": \"(?=\\\\b(module)\\\\b)\",\n                            \"end\":\n                                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\\\b)\",\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\b(module)\\\\b\",\n                                    \"end\":\n                                        \"(?=:?=|[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n                                    \"beginCaptures\": {\n                                        \"1\": {\n                                            \"name\":\n                                                \"markup.inserted keyword.control keyword.other variable.other.readwrite.instance\"\n                                        }\n                                    },\n                                    \"patterns\": [\n                                        { \"include\": \"#comment\" },\n                                        { \"include\": \"#module-path-simple\" },\n                                        {\n                                            \"match\": \"[[:upper:]][[:word:]]*\",\n                                            \"name\": \"support.class entity.name.class\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"begin\": \"(:=)|(=)\",\n                                    \"end\":\n                                        \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\\\b)\",\n                                    \"beginCaptures\": {\n                                        \"1\": { \"name\": \"markup.inserted keyword.control.less\" },\n                                        \"2\": { \"name\": \"markup.inserted keyword.control.less\" }\n                                    },\n                                    \"patterns\": [{ \"include\": \"#structure-expression\" }]\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"structure-expression\": {\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"comment\":\n                        \"FIXME: scan for :upper: or `val` to disambiguate types from signatures for hover\",\n                    \"begin\": \"\\\\((?=[[:space:]]*(\\\\b(val)\\\\b|[^'\\\\[<[:lower:]]))\",\n                    \"end\":\n                        \"\\\\)|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|with)\\\\b)\",\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        {\n                            \"comment\":\n                                \"FIXME: might need to refactor this or include more expressions\",\n                            \"include\": \"#structure-expression-block\"\n                        },\n                        {\n                            \"begin\": \"\\\\b(val)\\\\b\",\n                            \"end\":\n                                \"(?=\\\\))|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                            \"beginCaptures\": {\n                                \"1\": { \"name\": \"keyword.other\" }\n                            },\n                            \"patterns\": [\n                                { \"include\": \"#comment\" },\n                                {\n                                    \"match\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n                                    \"name\": \"support.class entity.name.class\"\n                                }\n                            ]\n                        },\n                        { \"include\": \"#module-path-simple\" },\n                        {\n                            \"begin\": \"(:)\",\n                            \"end\":\n                                \"(?=[\\\\)])|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val)\\\\b)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                }\n                            },\n                            \"patterns\": [{ \"include\": \"#signature-expression\" }]\n                        }\n                    ]\n                },\n                { \"include\": \"#module-path-simple\" },\n                { \"include\": \"#structure-expression-block\" }\n            ]\n        },\n        \"structure-expression-block\": {\n            \"begin\": \"{\",\n            \"end\": \"}\",\n            \"patterns\": [{ \"include\": \"#structure-expression-block-item\" }]\n        },\n        \"structure-expression-block-item\": {\n            \"patterns\": [\n                { \"include\": \"#attribute\" },\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-item-exception\" },\n                { \"include\": \"#module-item-external\" },\n                { \"include\": \"#module-item-include\" },\n                { \"include\": \"#module-item-let\" },\n                { \"include\": \"#module-item-class-type\" },\n                { \"include\": \"#module-item-module-type\" },\n                { \"include\": \"#module-item-module\" },\n                { \"include\": \"#module-item-open\" },\n                { \"include\": \"#module-item-type\" }\n            ]\n        },\n        \"type-annotation-rhs\": {\n            \"begin\": \"(?<![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])([:])(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])\",\n            \"end\":\n                \"(?=\\\\))|(?=[,;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#type-expression\" }]\n        },\n        \"type-expression\": {\n            \"patterns\": [\n                {\n                    \"match\": \"([\\\\.])\",\n                    \"name\": \"entity.name.function\"\n                },\n                { \"include\": \"#type-expression-atomic\" },\n                { \"include\": \"#type-expression-arrow\" }\n            ]\n        },\n        \"type-expression-atomic\": {\n            \"patterns\": [\n                { \"include\": \"#attribute\" },\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-path-extended-prefix\" },\n                { \"include\": \"#type-expression-label\" },\n                {\n                    \"match\": \"\\\\b(as)\\\\b\",\n                    \"name\": \"variable.other.class.js variable.interpolation storage.modifier\"\n                },\n                { \"include\": \"#type-expression-constructor\" },\n                { \"include\": \"#type-expression-object\" },\n                { \"include\": \"#type-expression-parens\" },\n                { \"include\": \"#type-expression-polymorphic-variant\" },\n                { \"include\": \"#type-expression-record\" },\n                { \"include\": \"#type-expression-variable\" }\n            ]\n        },\n        \"type-expression-arrow\": {\n            \"match\": \"=>\",\n            \"name\": \"markup.inserted keyword.control.less\"\n        },\n        \"type-expression-constructor\": {\n            \"match\": \"(_)(?![[:alnum:]])|\\\\b([_[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n            \"captures\": {\n                \"1\": { \"name\": \"comment\" },\n                \"2\": { \"name\": \"support.type\" }\n            }\n        },\n        \"type-expression-label\": {\n            \"begin\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b(::)\",\n            \"end\": \"(?<==>)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                },\n                \"2\": { \"name\": \"keyword.control\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#type-expression\" },\n                {\n                    \"match\": \"(\\\\?)\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" }\n                    }\n                }\n            ]\n        },\n        \"type-expression-object\": {\n            \"comment\": \"FIXME: separate sub-rules\",\n            \"begin\": \"(<)\",\n            \"end\": \"(>)\",\n            \"captures\": {\n                \"1\": { \"name\": \"entity.name.function\" }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"(\\\\.\\\\.)\",\n                    \"end\": \"(?=>)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"constant.language\" }\n                    }\n                },\n                {\n                    \"comment\": \"FIXME: method item\",\n                    \"begin\": \"(?=[_[:lower:]])\",\n                    \"end\": \"(,)|(?=>)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"comment\": \"FIXME: method name\",\n                            \"begin\": \"(?=[_[:lower:]])\",\n                            \"end\": \"(?=:)\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b\",\n                                    \"captures\": {\n                                        \"1\": {\n                                            \"name\":\n                                                \"markup.inserted constant.language support.property-value entity.name.filename\"\n                                        }\n                                    }\n                                }\n                            ]\n                        },\n                        {\n                            \"comment\": \"FIXME: method type\",\n                            \"begin\": \"(:)\",\n                            \"end\": \"(?=[,>])\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                }\n                            },\n                            \"patterns\": [{ \"include\": \"#type-expression\" }]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-expression-parens\": {\n            \"comment\": \"FIXME: proper tuple types\",\n            \"begin\": \"\\\\(\",\n            \"end\": \"\\\\)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(module)\\\\b\",\n                    \"end\": \"(?=[\\\\)])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.other\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#module-path-extended\" },\n                        { \"include\": \"#signature-expression-constraints\" }\n                    ]\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"keyword.control.less\"\n                },\n                { \"include\": \"#type-expression\" }\n            ]\n        },\n        \"type-expression-polymorphic-variant\": {\n            \"comment\": \"FIXME: proper parsing\",\n            \"begin\": \"(\\\\[)([<>])?\",\n            \"end\": \"(\\\\])\",\n            \"captures\": {\n                \"1\": { \"name\": \"entity.name.function\" },\n                \"2\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"(\\\\|)?(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])[[:space:]]*\",\n                    \"end\":\n                        \"(?=[;)}\\\\]]|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#value-expression-constructor\" },\n                        {\n                            \"match\": \"([:])|\\\\b(of)\\\\b|([&])\",\n                            \"captures\": {\n                                \"1\": { \"name\": \"keyword.control.less\" },\n                                \"2\": { \"name\": \"keyword.other\" },\n                                \"3\": {\n                                    \"name\":\n                                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                }\n                            }\n                        },\n                        { \"include\": \"#value-expression-constructor-polymorphic\" },\n                        { \"include\": \"#type-expression\" }\n                    ]\n                }\n            ]\n        },\n        \"type-expression-record\": {\n            \"begin\": \"{\",\n            \"end\": \"}\",\n            \"patterns\": [{ \"include\": \"#type-expression-record-item\" }]\n        },\n        \"type-expression-record-field-sans-modifier\": {\n            \"begin\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b\",\n            \"end\": \"(,)|(?=[,}])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"begin\": \"(:)\",\n                    \"end\": \"(?=[,}])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [{ \"include\": \"#type-expression\" }]\n                }\n            ]\n        },\n        \"type-expression-record-field\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(mutable)\\\\b\",\n                    \"end\": \"(?<=[,])|(?=})\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation storage.modifier\"\n                        }\n                    },\n                    \"patterns\": [{ \"include\": \"#type-expression-record-field-sans-modifier\" }]\n                },\n                { \"include\": \"#type-expression-record-field-sans-modifier\" }\n            ]\n        },\n        \"type-expression-record-item\": {\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#type-expression-record-field\" }\n            ]\n        },\n        \"type-expression-variable\": {\n            \"match\": \"(')([_[:lower:]][[:word:]]*)\\\\b(?!\\\\.[[:upper:]])\",\n            \"captures\": {\n                \"1\": { \"name\": \"comment\" },\n                \"2\": { \"name\": \"variable.parameter\" }\n            }\n        },\n        \"value-expression\": {\n            \"patterns\": [\n                { \"include\": \"#attribute\" },\n                { \"include\": \"#comment\" },\n                { \"include\": \"#extension-node\" },\n                { \"include\": \"#jsx\" },\n                { \"include\": \"#operator\" },\n                { \"include\": \"#value-expression-builtin\" },\n                { \"include\": \"#value-expression-if-then-else\" },\n                { \"include\": \"#value-expression-atomic\" },\n                { \"include\": \"#module-path-simple-prefix\" },\n                {\n                    \"match\": \"[:?]\",\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                },\n                { \"include\": \"#record-path\" }\n            ]\n        },\n        \"value-expression-atomic\": {\n            \"patterns\": [\n                { \"include\": \"#value-expression-literal\" },\n                { \"include\": \"#value-expression-literal-list-or-array\" },\n                { \"include\": \"#value-expression-for\" },\n                { \"include\": \"#value-expression-fun\" },\n                { \"include\": \"#value-expression-block-or-record-or-object\" },\n                { \"include\": \"#value-expression-label\" },\n                { \"include\": \"#value-expression-parens\" },\n                { \"include\": \"#value-expression-switch\" },\n                { \"include\": \"#value-expression-try\" },\n                { \"include\": \"#value-expression-while\" }\n            ]\n        },\n        \"value-expression-atomic-with-paths\": {\n            \"patterns\": [\n                { \"include\": \"#value-expression-atomic\" },\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#record-path-suffix\" }\n            ]\n        },\n        \"value-expression-block\": {\n            \"begin\": \"{\",\n            \"end\": \"}\",\n            \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n        },\n        \"value-expression-block-item\": {\n            \"patterns\": [\n                { \"include\": \"#module-item-let\" },\n                { \"include\": \"#module-item-open\" },\n                { \"include\": \"#value-expression\" }\n            ]\n        },\n        \"value-expression-block-look\": {\n            \"begin\":\n                \"(?![[:space:]]*($|\\\\.\\\\.\\\\.|([[:upper:]][[:word:]]*\\\\.)*([[:lower:]][[:word:]]*)[[:space:]]*(?:,|:(?![=]))))\",\n            \"end\": \"(?=})\",\n            \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n        },\n        \"value-expression-block-or-record-or-object\": {\n            \"begin\": \"{\",\n            \"end\": \"}\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#value-expression-object-look\" },\n                { \"include\": \"#value-expression-record-look\" },\n                { \"include\": \"#value-expression-block-look\" }\n            ]\n        },\n        \"value-expression-builtin\": {\n            \"match\":\n                \"\\\\b(assert|decr|failwith|fprintf|ignore|incr|land|lazy|lor|lsl|lsr|lxor|mod|new|not|printf|ref)\\\\b|\\\\b(raise)\\\\b\",\n            \"captures\": {\n                \"1\": { \"name\": \"keyword.control\" },\n                \"2\": { \"name\": \"keyword.control.trycatch\" }\n            }\n        },\n        \"value-expression-constructor\": {\n            \"match\": \"\\\\b([[:upper:]][[:word:]]*)\\\\b(?![[:space:]]*[\\\\.])\",\n            \"captures\": {\n                \"1\": { \"name\": \"constant.language\" }\n            }\n        },\n        \"value-expression-constructor-polymorphic\": {\n            \"match\": \"(`)([[:alpha:]][[:word:]]*)\\\\b(?!\\\\.)\",\n            \"captures\": {\n                \"1\": { \"name\": \"constant.other.symbol keyword.control.less variable.parameter\" },\n                \"2\": { \"name\": \"constant.language\" }\n            }\n        },\n        \"value-expression-for\": {\n            \"begin\": \"(?=\\\\b(for)\\\\b)\",\n            \"end\":\n                \"(?<=})|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#value-expression-for-head\" },\n                { \"include\": \"#value-expression-block\" }\n            ]\n        },\n        \"value-expression-for-head\": {\n            \"begin\": \"(?=\\\\b(for)\\\\b)\",\n            \"end\":\n                \"(?={)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(for)\\\\b\",\n                    \"end\":\n                        \"(?=\\\\b(in)\\\\b)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.loop\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#comment\" }, { \"include\": \"#pattern-variable\" }]\n                },\n                {\n                    \"begin\": \"\\\\b(in)\\\\b\",\n                    \"end\":\n                        \"(?=\\\\b(to)\\\\b)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.loop\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        { \"include\": \"#value-expression-atomic-with-paths\" }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b(to)\\\\b\",\n                    \"end\":\n                        \"(?={)|(?=[;]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.loop\" }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        { \"include\": \"#value-expression-atomic-with-paths\" }\n                    ]\n                },\n                { \"include\": \"#value-expression-block\" }\n            ]\n        },\n        \"value-expression-fun\": {\n            \"begin\": \"\\\\b(fun)\\\\b\",\n            \"end\":\n                \"(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#value-expression-fun-pattern-match-rule-lhs\" },\n                { \"include\": \"#value-expression-fun-pattern-match-rule-rhs\" }\n            ]\n        },\n        \"value-expression-fun-pattern-match-rule-lhs\": {\n            \"begin\": \"(?=\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|(?<=fun)\",\n            \"end\":\n                \"(\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))|(?==>)|(?=[;\\\\)}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"applyEndPatternLast\": true,\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [{ \"include\": \"#pattern-guard\" }, { \"include\": \"#pattern\" }]\n        },\n        \"value-expression-fun-pattern-match-rule-rhs\": {\n            \"begin\": \"(=>)\",\n            \"end\": \"(?=[;\\\\)}]|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\])|\\\\b(and)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.less\" }\n            },\n            \"patterns\": [{ \"include\": \"#value-expression\" }]\n        },\n        \"value-expression-if-then-else\": {\n            \"begin\": \"\\\\b(if)\\\\b\",\n            \"end\": \"(?=[;\\\\)\\\\]}])\",\n            \"applyEndPatternLast\": true,\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.conditional\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"begin\": \"\\\\b(else)\\\\b\",\n                    \"end\": \"(?=[;\\\\)\\\\]}])\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.conditional\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#value-expression\" }]\n                },\n                { \"include\": \"#value-expression-atomic-with-paths\" }\n            ]\n        },\n        \"value-expression-lazy\": {\n            \"comment\": \"FIXME\",\n            \"match\": \"\\\\b(lazy)\\\\b\",\n            \"captures\": {\n                \"1\": { \"name\": \"keyword.other\" }\n            }\n        },\n        \"value-expression-label\": {\n            \"begin\": \"\\\\b([_[:lower:]][[:word:]]*)\\\\b[[:space:]]*(::)(\\\\?)?\",\n            \"end\": \"(?![[:space:]])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\":\n                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                },\n                \"2\": { \"name\": \"keyword.control\" },\n                \"3\": { \"name\": \"storage.type\" }\n            },\n            \"patterns\": [{ \"include\": \"#value-expression\" }]\n        },\n        \"value-expression-literal\": {\n            \"patterns\": [\n                { \"include\": \"#value-expression-literal-boolean\" },\n                { \"include\": \"#value-expression-literal-character\" },\n                { \"include\": \"#value-expression-constructor\" },\n                { \"include\": \"#value-expression-constructor-polymorphic\" },\n                { \"include\": \"#value-expression-lazy\" },\n                { \"include\": \"#value-expression-literal-numeric\" },\n                { \"include\": \"#value-expression-literal-string\" },\n                { \"include\": \"#value-expression-literal-unit\" }\n            ]\n        },\n        \"value-expression-literal-boolean\": {\n            \"match\": \"\\\\b(false|true)\\\\b\",\n            \"name\": \"constant.language\"\n        },\n        \"value-expression-literal-character\": {\n            \"match\":\n                \"(')([[:space:]]|[[:graph:]]|\\\\\\\\[\\\\\\\\\\\"'ntbr]|\\\\\\\\[[:digit:]][[:digit:]][[:digit:]]|\\\\\\\\x[[:xdigit:]][[:xdigit:]]|\\\\\\\\o[0-3][0-7][0-7])(')\",\n            \"name\": \"constant.character\"\n        },\n        \"value-expression-literal-list-or-array\": {\n            \"begin\": \"(\\\\[\\\\|?)(?![@%])\",\n            \"end\": \"(\\\\|?\\\\])\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"constant.language.list\" }\n            },\n            \"endCaptures\": {\n                \"1\": { \"name\": \"constant.language.list\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#value-expression-literal-list-or-array-separator\" },\n                { \"include\": \"#value-expression\" },\n                { \"include\": \"#value-expression-literal-list-or-array\" }\n            ]\n        },\n        \"value-expression-literal-list-or-array-separator\": {\n            \"match\": \"(,)|(\\\\.\\\\.\\\\.)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                },\n                \"2\": { \"name\": \"keyword.control\" }\n            }\n        },\n        \"value-expression-literal-numeric\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"([-])?([[:digit:]][_[:digit:]]*)(?:(\\\\.)([_[:digit:]]*))?(?:([eE])([\\\\-\\\\+])?([[:digit:]][_[:digit:]]*))?(?![bBoOxX])\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" },\n                        \"2\": { \"name\": \"constant.numeric\" },\n                        \"3\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"4\": { \"name\": \"constant.numeric\" },\n                        \"5\": { \"name\": \"keyword.control.less\" },\n                        \"6\": { \"name\": \"keyword.control.less\" },\n                        \"7\": { \"name\": \"constant.numeric\" }\n                    }\n                },\n                {\n                    \"match\":\n                        \"([-])?(0[xX])([[:xdigit:]][_[:xdigit:]]*)(?:(\\\\.)([_[:xdigit:]]*))?(?:([pP])([\\\\-\\\\+])?([[:digit:]][_[:digit:]]*))?\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" },\n                        \"2\": { \"name\": \"keyword.control.less\" },\n                        \"3\": { \"name\": \"constant.numeric\" },\n                        \"4\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        },\n                        \"5\": { \"name\": \"constant.numeric\" },\n                        \"6\": { \"name\": \"keyword.control.less\" },\n                        \"7\": { \"name\": \"keyword.control.less\" },\n                        \"8\": { \"name\": \"constant.numeric\" }\n                    }\n                },\n                {\n                    \"match\": \"([-])?(0[oO])([0-7][_0-7]*)\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" },\n                        \"2\": { \"name\": \"keyword.control.less\" },\n                        \"3\": { \"name\": \"constant.numeric\" }\n                    }\n                },\n                {\n                    \"match\": \"([-])?(0[bB])([0-1][_0-1]*)\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" },\n                        \"2\": { \"name\": \"keyword.control.less\" },\n                        \"3\": { \"name\": \"constant.numeric\" }\n                    }\n                }\n            ]\n        },\n        \"value-expression-literal-string\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<![[:alpha:]])js_expr(?!=[[:word:]])\",\n                    \"end\": \"(?<=\\\")|(\\\\|)([_[:lower:]]*)?(})|(?=[^[:space:]\\\"{])\",\n                    \"endCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.flow\" },\n                        \"2\": { \"name\": \"constant.language\" },\n                        \"3\": { \"name\": \"keyword.control.flow\" }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"({)([_[:lower:]]*)?(\\\\|)\",\n                            \"end\": \"(?=\\\\|\\\\2})\",\n                            \"comment\": \"meta.separator\",\n                            \"beginCaptures\": {\n                                \"1\": { \"name\": \"keyword.control.flow\" },\n                                \"2\": { \"name\": \"constant.language\" },\n                                \"3\": { \"name\": \"keyword.control.flow\" }\n                            },\n                            \"patterns\": [{ \"include\": \"source.js\" }]\n                        },\n                        {\n                            \"begin\": \"\\\"\",\n                            \"end\": \"\\\"\",\n                            \"comment\": \"meta.separator\",\n                            \"patterns\": [{ \"include\": \"source.js\" }]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"({)([_[:lower:]]*)?(\\\\|)\",\n                    \"end\": \"(\\\\|)(\\\\2)(})\",\n                    \"name\": \"string.double string.regexp\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.flow\" },\n                        \"2\": { \"name\": \"constant.language\" },\n                        \"3\": { \"name\": \"keyword.control.flow\" }\n                    },\n                    \"endCaptures\": {\n                        \"1\": { \"name\": \"keyword.control.flow\" },\n                        \"2\": { \"name\": \"constant.language\" },\n                        \"3\": { \"name\": \"keyword.control.flow\" }\n                    }\n                },\n                {\n                    \"begin\": \"\\\"\",\n                    \"end\": \"\\\"\",\n                    \"name\": \"string.double string.regexp\",\n                    \"patterns\": [{ \"include\": \"#value-expression-literal-string-escape\" }]\n                }\n            ]\n        },\n        \"value-expression-literal-string-escape\": {\n            \"patterns\": [\n                {\n                    \"comment\": \"FIXME: make escapes into separate rule\",\n                    \"match\":\n                        \"\\\\\\\\[\\\\\\\\\\\"'ntbr ]|\\\\\\\\[[:digit:]][[:digit:]][[:digit:]]|\\\\\\\\x[[:xdigit:]][[:xdigit:]]|\\\\\\\\o[0-3][0-7][0-7]\",\n                    \"name\": \"constant.character\"\n                },\n                {\n                    \"match\": \"(@)([ \\\\[\\\\],.]|\\\\\\\\n)\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"keyword.control.less\" },\n                        \"2\": { \"name\": \"constant.language\" }\n                    }\n                },\n                {\n                    \"comment\": \"FIXME: don't highlight in external strings\",\n                    \"match\": \"(%)([ads])?\",\n                    \"captures\": {\n                        \"1\": { \"name\": \"constant.language\" },\n                        \"2\": {\n                            \"name\":\n                                \"variable.other.readwrite.instance string.other.link variable.language\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"value-expression-literal-unit\": {\n            \"match\": \"\\\\(\\\\)\",\n            \"name\": \"constant.language.unit\"\n        },\n        \"value-expression-object-look\": {\n            \"comment\": \"FIXME: is there a better way than listing all the keywords?\",\n            \"begin\": \"(?:\\\\G|^)[[:space:]]*(?=method)\",\n            \"end\": \"(?=})\",\n            \"patterns\": [{ \"include\": \"#object-item\" }]\n        },\n        \"value-expression-parens\": {\n            \"begin\": \"(?=\\\\()\",\n            \"end\":\n                \"(\\\\))|(?=[;}]|\\\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"endCaptures\": {},\n            \"patterns\": [\n                { \"include\": \"#condition-lhs\" },\n                { \"include\": \"#value-expression-parens-lhs\" },\n                { \"include\": \"#type-annotation-rhs\" }\n            ]\n        },\n        \"value-expression-parens-lhs\": {\n            \"begin\": \"(\\\\()|(,)\",\n            \"end\":\n                \"(?=[?,:\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\":\n                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\b(module)\\\\b\",\n                    \"end\": \"(?=\\\\))\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.other\" }\n                    },\n                    \"patterns\": [{ \"include\": \"#module-path-simple\" }]\n                },\n                { \"include\": \"#value-expression\" }\n            ]\n        },\n        \"value-expression-record-field\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(\\\\.\\\\.\\\\.)\",\n                    \"end\": \"(,)|(?=})\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"keyword.control\" }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#comment\" },\n                        { \"include\": \"#module-path-simple-prefix\" },\n                        {\n                            \"begin\": \"(?=[\\\\.])\",\n                            \"end\": \"(?=[:,])\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\b[[:lower:]][[:word:]]*\\\\b\",\n                                    \"name\":\n                                        \"markup.inserted constant.language support.property-value entity.name.filename\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"(:)\",\n                            \"end\": \"(?=[,}])\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                }\n                            },\n                            \"patterns\": [{ \"include\": \"#value-expression\" }]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b[[:upper:]][[:word:]]*\\\\b\",\n                    \"end\": \"(,)|(?=})\",\n                    \"beginCaptures\": {\n                        \"1\": { \"name\": \"support.class entity.name.class\" }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        { \"include\": \"#module-path-simple-prefix\" },\n                        {\n                            \"begin\": \"(:)\",\n                            \"end\": \"(?=[,}])\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                }\n                            },\n                            \"patterns\": [{ \"include\": \"#value-expression\" }]\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\b([[:lower:]][[:word:]]*)\\\\b\",\n                    \"end\": \"(,)|(?=})\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"markup.inserted constant.language support.property-value entity.name.filename\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\":\n                                \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(:)\",\n                            \"end\": \"(?=[,}])\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"variable.other.class.js variable.interpolation keyword.operator keyword.control\"\n                                }\n                            },\n                            \"patterns\": [{ \"include\": \"#value-expression\" }]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"value-expression-record-item\": {\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#module-path-simple-prefix\" },\n                { \"include\": \"#value-expression-record-field\" }\n            ]\n        },\n        \"value-expression-switch\": {\n            \"begin\": \"\\\\b(switch)\\\\b\",\n            \"end\": \"(?<=})\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.switch\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#value-expression-switch-head\" },\n                { \"include\": \"#value-expression-switch-body\" }\n            ]\n        },\n        \"value-expression-switch-body\": {\n            \"begin\": \"{\",\n            \"end\": \"}\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#value-expression-switch-pattern-match-rule\" }\n            ]\n        },\n        \"value-expression-switch-head\": {\n            \"begin\": \"(?<=switch)\",\n            \"end\":\n                \"(?<!switch)(?={)|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"begin\": \"\\\\G[[:space:]]*+{\",\n                    \"end\": \"}[[:space:]]*+\",\n                    \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n                },\n                { \"include\": \"#value-expression-atomic-with-paths\" }\n            ]\n        },\n        \"value-expression-switch-pattern-match-rule\": {\n            \"patterns\": [\n                { \"include\": \"#value-expression-switch-pattern-match-rule-lhs\" },\n                { \"include\": \"#value-expression-switch-pattern-match-rule-rhs\" }\n            ]\n        },\n        \"value-expression-switch-pattern-match-rule-lhs\": {\n            \"begin\": \"(?=\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))\",\n            \"end\": \"(?==>|[;\\\\)}])\",\n            \"patterns\": [{ \"include\": \"#pattern-guard\" }, { \"include\": \"#pattern\" }]\n        },\n        \"value-expression-switch-pattern-match-rule-rhs\": {\n            \"begin\": \"(=>)\",\n            \"end\": \"(?=}|\\\\|(?![#\\\\-:!?.@*/&%^+<=>|~$\\\\\\\\]))\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.less\" }\n            },\n            \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n        },\n        \"value-expression-try\": {\n            \"begin\": \"\\\\b(try)\\\\b\",\n            \"end\":\n                \"(?<=})|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.trycatch\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#value-expression-try-head\" },\n                { \"include\": \"#value-expression-switch-body\" }\n            ]\n        },\n        \"value-expression-try-head\": {\n            \"begin\": \"(?<=try)\",\n            \"end\":\n                \"(?<!try)(?={)|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                {\n                    \"begin\": \"\\\\G[[:space:]]*+{\",\n                    \"end\": \"}[[:space:]]*+\",\n                    \"patterns\": [{ \"include\": \"#value-expression-block-item\" }]\n                },\n                { \"include\": \"#value-expression-atomic-with-paths\" }\n            ]\n        },\n        \"value-expression-while\": {\n            \"begin\": \"\\\\b(while)\\\\b\",\n            \"end\":\n                \"(?<=})|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"beginCaptures\": {\n                \"1\": { \"name\": \"keyword.control.loop\" }\n            },\n            \"patterns\": [\n                { \"include\": \"#value-expression-while-head\" },\n                { \"include\": \"#value-expression-block\" }\n            ]\n        },\n        \"value-expression-while-head\": {\n            \"begin\": \"(?<=while)[[:space:]]*+\",\n            \"end\":\n                \"(?={)|(?=[;\\\\)]|\\\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\\\b)\",\n            \"patterns\": [\n                { \"include\": \"#comment\" },\n                { \"include\": \"#value-expression-atomic-with-paths\" }\n            ]\n        },\n        \"value-expression-record-look\": {\n            \"begin\":\n                \"(?=\\\\.\\\\.\\\\.|([[:upper:]][[:word:]]*\\\\.)*([[:lower:]][[:word:]]*)[[:space:]]*[,:}])\",\n            \"end\": \"(?=})\",\n            \"patterns\": [{ \"include\": \"#value-expression-record-item\" }]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/ruby/syntaxes/ruby.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/textmate/ruby.tmbundle/blob/master/Syntaxes/Ruby.plist\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/textmate/ruby.tmbundle/commit/74713556df10fbc7b1f9e99013ab1e34cd836f56\",\n    \"name\": \"Ruby\",\n    \"scopeName\": \"source.ruby\",\n    \"comment\":\n        \"\\n\\tTODO: unresolved issues\\n\\n\\ttext:\\n\\t\\\"p <<end\\n\\tprint me!\\n\\tend\\\"\\n\\tsymptoms:\\n\\tnot recognized as a heredoc\\n\\tsolution:\\n\\tthere is no way to distinguish perfectly between the << operator and the start\\n\\tof a heredoc. Currently, we require assignment to recognize a heredoc. More\\n\\trefinement is possible.\\n\\t• Heredocs with indented terminators (<<-) are always distinguishable, however.\\n\\t• Nested heredocs are not really supportable at present\\n\\n\\ttext:\\n\\tprint <<-'THERE' \\n\\tThis is single quoted. \\n\\tThe above used #{Time.now} \\n\\tTHERE \\n\\tsymtoms:\\n\\tFrom Programming Ruby p306; should be a non-interpolated heredoc.\\n\\t\\n    text:\\n    val?(a):p(b)\\n    val?'a':'b'\\n    symptoms:\\n    ':p' is recognized as a symbol.. its 2 things ':' and 'p'.\\n    :'b' has same problem.\\n    solution:\\n    ternary operator rule, precedence stuff, symbol rule.\\n    but also consider 'a.b?(:c)' ??\\n\",\n    \"patterns\": [\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.class.ruby\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.class.ruby\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.operator.other.ruby\"\n                },\n                \"4\": {\n                    \"name\": \"entity.other.inherited-class.ruby\"\n                },\n                \"5\": {\n                    \"name\": \"keyword.operator.other.ruby\"\n                },\n                \"6\": {\n                    \"name\": \"variable.other.object.ruby\"\n                }\n            },\n            \"match\":\n                \"^\\\\s*(class)\\\\s+(?:([.a-zA-Z0-9_:]+)(?:\\\\s*(<)\\\\s*([.a-zA-Z0-9_:]+))?|(<<)\\\\s*([.a-zA-Z0-9_:]+))\",\n            \"name\": \"meta.class.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.module.ruby\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.module.ruby\"\n                },\n                \"3\": {\n                    \"name\": \"entity.other.inherited-class.module.first.ruby\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.separator.inheritance.ruby\"\n                },\n                \"5\": {\n                    \"name\": \"entity.other.inherited-class.module.second.ruby\"\n                },\n                \"6\": {\n                    \"name\": \"punctuation.separator.inheritance.ruby\"\n                },\n                \"7\": {\n                    \"name\": \"entity.other.inherited-class.module.third.ruby\"\n                },\n                \"8\": {\n                    \"name\": \"punctuation.separator.inheritance.ruby\"\n                }\n            },\n            \"match\": \"^\\\\s*(module)\\\\s+(([A-Z]\\\\w*(::))?([A-Z]\\\\w*(::))?([A-Z]\\\\w*(::))*[A-Z]\\\\w*)\",\n            \"name\": \"meta.module.ruby\"\n        },\n        {\n            \"comment\":\n                \"else if is a common mistake carried over from other languages. it works if you put in a second end, but it’s never what you want.\",\n            \"match\": \"(?<!\\\\.)\\\\belse(\\\\s)+if\\\\b\",\n            \"name\": \"invalid.deprecated.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.ruby\"\n                }\n            },\n            \"comment\": \"symbols as hash key (1.9 syntax)\",\n            \"match\": \"(?>[a-zA-Z_]\\\\w*(?>[?!])?)(:)(?!:)\",\n            \"name\": \"constant.other.symbol.hashkey.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.ruby\"\n                }\n            },\n            \"comment\": \"symbols as hash key (1.8 syntax)\",\n            \"match\": \"(?<!:)(:)(?>[a-zA-Z_]\\\\w*(?>[?!])?)(?=\\\\s*=>)\",\n            \"name\": \"constant.other.symbol.hashkey.ruby\"\n        },\n        {\n            \"comment\": \"everything being a reserved word, not a value and needing a 'end' is a..\",\n            \"match\":\n                \"(?<!\\\\.)\\\\b(BEGIN|begin|case|class|else|elsif|END|end|ensure|for|if|in|module|rescue|then|unless|until|when|while)\\\\b(?![?!])\",\n            \"name\": \"keyword.control.ruby\"\n        },\n        {\n            \"comment\": \"contextual smart pair support for block parameters\",\n            \"match\": \"(?<!\\\\.)\\\\bdo\\\\b\",\n            \"name\": \"keyword.control.start-block.ruby\"\n        },\n        {\n            \"comment\": \"contextual smart pair support\",\n            \"match\": \"(?<=\\\\{)(\\\\s+)\",\n            \"name\": \"meta.syntax.ruby.start-block\"\n        },\n        {\n            \"match\":\n                \"(?<!\\\\.)\\\\b(alias|alias_method|block_given[?]|break|defined[?]|iterator[?]|next|redo|retry|return|super|undef|yield)(\\\\b|(?<=[?]))(?![?!])\",\n            \"name\": \"keyword.control.pseudo-method.ruby\"\n        },\n        {\n            \"match\": \"\\\\b(nil|true|false)\\\\b(?![?!])\",\n            \"name\": \"constant.language.ruby\"\n        },\n        {\n            \"match\": \"\\\\b(__(FILE|LINE)__)\\\\b(?![?!])\",\n            \"name\": \"variable.language.ruby\"\n        },\n        {\n            \"match\": \"\\\\b(self)\\\\b(?![?!])\",\n            \"name\": \"variable.language.self.ruby\"\n        },\n        {\n            \"comment\": \" everything being a method but having a special function is a..\",\n            \"match\":\n                \"\\\\b(initialize|new|loop|include|extend|prepend|fail|raise|attr_reader|attr_writer|attr_accessor|attr|catch|throw|private|private_class_method|module_function|public|public_class_method|protected|refine|using)\\\\b(?![?!])\",\n            \"name\": \"keyword.other.special-method.ruby\"\n        },\n        {\n            \"begin\": \"\\\\b(?<!\\\\.|::)(require|require_relative)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.special-method.ruby\"\n                }\n            },\n            \"end\": \"$|(?=#|\\\\})\",\n            \"name\": \"meta.require.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.ruby\"\n                }\n            },\n            \"match\": \"(@)[a-zA-Z_]\\\\w*\",\n            \"name\": \"variable.other.readwrite.instance.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.ruby\"\n                }\n            },\n            \"match\": \"(@@)[a-zA-Z_]\\\\w*\",\n            \"name\": \"variable.other.readwrite.class.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.ruby\"\n                }\n            },\n            \"match\": \"(\\\\$)[a-zA-Z_]\\\\w*\",\n            \"name\": \"variable.other.readwrite.global.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.variable.ruby\"\n                }\n            },\n            \"match\":\n                \"(\\\\$)(!|@|&|`|'|\\\\+|\\\\d+|~|=|/|\\\\\\\\|,|;|\\\\.|<|>|_|\\\\*|\\\\$|\\\\?|:|\\\"|-[0adFiIlpvw])\",\n            \"name\": \"variable.other.readwrite.global.pre-defined.ruby\"\n        },\n        {\n            \"begin\": \"\\\\b(ENV)\\\\[\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"variable.other.constant.ruby\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"name\": \"meta.environment-variable.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        {\n            \"match\": \"\\\\b[A-Z]\\\\w*(?=((\\\\.|::)[A-Za-z]|\\\\[))\",\n            \"name\": \"support.class.ruby\"\n        },\n        {\n            \"match\":\n                \"\\\\b(abort|at_exit|autoload[?]?|binding|callcc|caller|caller_locations|chomp|chop|eval|exec|exit|exit!|fork|format|gets|global_variables|gsub|lambda|load|local_variables|open|p|print|printf|proc|putc|puts|rand|readline|readlines|select|set_trace_func|sleep|spawn|sprintf|srand|sub|syscall|system|test|trace_var|trap|untrace_var|warn)(\\\\b|(?<=[?!]))(?![?!])\",\n            \"name\": \"support.function.kernel.ruby\"\n        },\n        {\n            \"match\": \"\\\\b[_A-Z]\\\\w*\\\\b\",\n            \"name\": \"variable.other.constant.ruby\"\n        },\n        {\n            \"begin\":\n                \"(?x)\\n\\t\\t\\t         (?=def\\\\b)                                                      # an optimization to help Oniguruma fail fast\\n\\t\\t\\t         (?<=^|\\\\s)(def)\\\\s+                                              # the def keyword\\n\\t\\t\\t         ( (?>[a-zA-Z_]\\\\w*(?>\\\\.|::))?                                   # a method name prefix\\n\\t\\t\\t           (?>[a-zA-Z_]\\\\w*(?>[?!]|=(?!>))?                              # the method name\\n\\t\\t\\t           |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\\\\|^]|\\\\*\\\\*?|=?~|[-+]@?|\\\\[\\\\]=?) )  # …or an operator method\\n\\t\\t\\t         \\\\s*(\\\\()                                                        # the openning parenthesis for arguments\\n\\t\\t\\t        \",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.def.ruby\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.ruby\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.parameters.ruby\"\n                }\n            },\n            \"comment\":\n                \"the method pattern comes from the symbol pattern, see there for a explaination\",\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.ruby\"\n                }\n            },\n            \"name\": \"meta.function.method.with-arguments.ruby\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?=[&*_a-zA-Z])\",\n                    \"end\": \"(?=[,)])\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"storage.type.variable.ruby\"\n                                },\n                                \"2\": {\n                                    \"name\": \"constant.other.symbol.hashkey.parameter.function.ruby\"\n                                },\n                                \"3\": {\n                                    \"name\": \"punctuation.definition.constant.ruby\"\n                                },\n                                \"4\": {\n                                    \"name\": \"variable.parameter.function.ruby\"\n                                }\n                            },\n                            \"match\": \"\\\\G([&*]?)(?:([_a-zA-Z]\\\\w*(:))|([_a-zA-Z]\\\\w*))\"\n                        },\n                        {\n                            \"include\": \"#parens\"\n                        },\n                        {\n                            \"include\": \"#braces\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ],\n            \"repository\": {\n                \"braces\": {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.ruby\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parens\"\n                        },\n                        {\n                            \"include\": \"#braces\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                \"parens\": {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.function.end.ruby\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parens\"\n                        },\n                        {\n                            \"include\": \"#braces\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            }\n        },\n        {\n            \"begin\":\n                \"(?x)\\n\\t\\t\\t         (?=def\\\\b)                                                      # an optimization to help Oniguruma fail fast\\n\\t\\t\\t         (?<=^|\\\\s)(def)\\\\s+                                              # the def keyword\\n\\t\\t\\t         ( (?>[a-zA-Z_]\\\\w*(?>\\\\.|::))?                                   # a method name prefix\\n\\t\\t\\t           (?>[a-zA-Z_]\\\\w*(?>[?!]|=(?!>))?                              # the method name\\n\\t\\t\\t           |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\\\\|^]|\\\\*\\\\*?|=?~|[-+]@?|\\\\[\\\\]=?) )  # …or an operator method\\n\\t\\t\\t         [ \\\\t]                                                          # the space separating the arguments\\n\\t\\t\\t         (?=[ \\\\t]*[^\\\\s#;])                                              # make sure arguments and not a comment follow\\n\\t\\t\\t        \",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.def.ruby\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.ruby\"\n                }\n            },\n            \"comment\": \"same as the previous rule, but without parentheses around the arguments\",\n            \"end\": \"$\",\n            \"name\": \"meta.function.method.with-arguments.ruby\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?![\\\\s,])\",\n                    \"end\": \"(?=,|$)\",\n                    \"patterns\": [\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"storage.type.variable.ruby\"\n                                },\n                                \"2\": {\n                                    \"name\": \"constant.other.symbol.hashkey.parameter.function.ruby\"\n                                },\n                                \"3\": {\n                                    \"name\": \"punctuation.definition.constant.ruby\"\n                                },\n                                \"4\": {\n                                    \"name\": \"variable.parameter.function.ruby\"\n                                }\n                            },\n                            \"match\": \"\\\\G([&*]?)(?:([_a-zA-Z]\\\\w*(:))|([_a-zA-Z]\\\\w*))\",\n                            \"name\": \"variable.parameter.function.ruby\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.def.ruby\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.function.ruby\"\n                }\n            },\n            \"comment\": \" the optional name is just to catch the def also without a method-name\",\n            \"match\":\n                \"(?x)\\n\\t\\t\\t         (?=def\\\\b)                                                           # an optimization to help Oniguruma fail fast\\n\\t\\t\\t         (?<=^|\\\\s)(def)\\\\b                                                    # the def keyword\\n\\t\\t\\t         ( \\\\s+                                                               # an optional group of whitespace followed by…\\n\\t\\t\\t           ( (?>[a-zA-Z_]\\\\w*(?>\\\\.|::))?                                      # a method name prefix\\n\\t\\t\\t             (?>[a-zA-Z_]\\\\w*(?>[?!]|=(?!>))?                                 # the method name\\n\\t\\t\\t             |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\\\\|^]|\\\\*\\\\*?|=?~|[-+]@?|\\\\[\\\\]=?) ) )?  # …or an operator method\\n\\t\\t\\t        \",\n            \"name\": \"meta.function.method.without-arguments.ruby\"\n        },\n        {\n            \"match\":\n                \"\\\\b\\\\d(?>_?\\\\d)*(?=\\\\.\\\\d|[eE])(\\\\.\\\\d(?>_?\\\\d)*)?([eE][-+]?\\\\d(?>_?\\\\d)*)?r?i?\\\\b\",\n            \"name\": \"constant.numeric.float.ruby\"\n        },\n        {\n            \"match\": \"\\\\b(0|(0[dD]\\\\d|[1-9])(?>_?\\\\d)*)r?i?\\\\b\",\n            \"name\": \"constant.numeric.integer.ruby\"\n        },\n        {\n            \"match\": \"\\\\b0[xX]\\\\h(?>_?\\\\h)*r?i?\\\\b\",\n            \"name\": \"constant.numeric.hex.ruby\"\n        },\n        {\n            \"match\": \"\\\\b0[bB][01](?>_?[01])*r?i?\\\\b\",\n            \"name\": \"constant.numeric.binary.ruby\"\n        },\n        {\n            \"match\": \"\\\\b0([oO]?[0-7](?>_?[0-7])*)?r?i?\\\\b\",\n            \"name\": \"constant.numeric.octal.ruby\"\n        },\n        {\n            \"begin\": \":'\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.constant.ruby\"\n                }\n            },\n            \"end\": \"'\",\n            \"name\": \"constant.other.symbol.single-quoted.ruby\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\['\\\\\\\\]\",\n                    \"name\": \"constant.character.escape.ruby\"\n                }\n            ]\n        },\n        {\n            \"begin\": \":\\\"\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.constant.ruby\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"name\": \"constant.other.symbol.double-quoted.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_ruby\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Needs higher precidence than regular expressions.\",\n            \"match\": \"(?<!\\\\()/=\",\n            \"name\": \"keyword.operator.assignment.augmented.ruby\"\n        },\n        {\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ruby\"\n                }\n            },\n            \"comment\": \"single quoted string (does not allow interpolation)\",\n            \"end\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.ruby\"\n                }\n            },\n            \"name\": \"string.quoted.single.ruby\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\'|\\\\\\\\\\\\\\\\\",\n                    \"name\": \"constant.character.escape.ruby\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ruby\"\n                }\n            },\n            \"comment\": \"double quoted string (allows for interpolation)\",\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.ruby\"\n                }\n            },\n            \"name\": \"string.quoted.double.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_ruby\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"`\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ruby\"\n                }\n            },\n            \"comment\": \"execute string (allows for interpolation)\",\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.ruby\"\n                }\n            },\n            \"name\": \"string.interpolated.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_ruby\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"include\": \"#percent_literals\"\n        },\n        {\n            \"begin\":\n                \"(?x)\\n\\t\\t\\t   (?:\\n\\t\\t\\t     ^                      # beginning of line\\n\\t\\t\\t   | (?<=                   # or look-behind on:\\n\\t\\t\\t       [=>~(?:\\\\[,|&;]\\n\\t\\t\\t     | [\\\\s;]if\\\\s\\t\\t\\t# keywords\\n\\t\\t\\t     | [\\\\s;]elsif\\\\s\\n\\t\\t\\t     | [\\\\s;]while\\\\s\\n\\t\\t\\t     | [\\\\s;]unless\\\\s\\n\\t\\t\\t     | [\\\\s;]when\\\\s\\n\\t\\t\\t     | [\\\\s;]assert_match\\\\s\\n\\t\\t\\t     | [\\\\s;]or\\\\s\\t\\t\\t# boolean opperators\\n\\t\\t\\t     | [\\\\s;]and\\\\s\\n\\t\\t\\t     | [\\\\s;]not\\\\s\\n\\t\\t\\t     | [\\\\s.]index\\\\s\\t\\t\\t# methods\\n\\t\\t\\t     | [\\\\s.]scan\\\\s\\n\\t\\t\\t     | [\\\\s.]sub\\\\s\\n\\t\\t\\t     | [\\\\s.]sub!\\\\s\\n\\t\\t\\t     | [\\\\s.]gsub\\\\s\\n\\t\\t\\t     | [\\\\s.]gsub!\\\\s\\n\\t\\t\\t     | [\\\\s.]match\\\\s\\n\\t\\t\\t     )\\n\\t\\t\\t   | (?<=                  # or a look-behind with line anchor:\\n\\t\\t\\t        ^when\\\\s            # duplication necessary due to limits of regex\\n\\t\\t\\t      | ^if\\\\s\\n\\t\\t\\t      | ^elsif\\\\s\\n\\t\\t\\t      | ^while\\\\s\\n\\t\\t\\t      | ^unless\\\\s\\n\\t\\t\\t      )\\n\\t\\t\\t   )\\n\\t\\t\\t   \\\\s*((/))(?![*+{}?])\\n\\t\\t\\t\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"string.regexp.classic.ruby\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.ruby\"\n                }\n            },\n            \"comment\":\n                \"regular expressions (normal)\\n\\t\\t\\twe only start a regexp if the character before it (excluding whitespace)\\n\\t\\t\\tis what we think is before a regexp\\n\\t\\t\\t\",\n            \"contentName\": \"string.regexp.classic.ruby\",\n            \"end\": \"((/[eimnosux]*))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#regex_sub\"\n                }\n            ]\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.constant.ruby\"\n                }\n            },\n            \"comment\": \"symbols\",\n            \"match\":\n                \"(?<!:)(:)(?>[a-zA-Z_]\\\\w*(?>[?!]|=(?![>=]))?|===?|>[>=]?|<=>|<[<=]?|[%&`/\\\\|]|\\\\*\\\\*?|=?~|[-+]@?|\\\\[\\\\]=?|(@@?|\\\\$)[a-zA-Z_]\\\\w*)\",\n            \"name\": \"constant.other.symbol.ruby\"\n        },\n        {\n            \"begin\": \"^=begin\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.ruby\"\n                }\n            },\n            \"comment\": \"multiline comments\",\n            \"end\": \"^=end\",\n            \"name\": \"comment.block.documentation.ruby\"\n        },\n        {\n            \"begin\": \"(^[ \\\\t]+)?(?=#)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.comment.leading.ruby\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"#\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.ruby\"\n                        }\n                    },\n                    \"end\": \"\\\\n\",\n                    \"name\": \"comment.line.number-sign.ruby\"\n                }\n            ]\n        },\n        {\n            \"comment\":\n                \"\\n\\t\\t\\tmatches questionmark-letters.\\n\\n\\t\\t\\texamples (1st alternation = hex):\\n\\t\\t\\t?\\\\x1     ?\\\\x61\\n\\n\\t\\t\\texamples (2nd alternation = octal):\\n\\t\\t\\t?\\\\0      ?\\\\07     ?\\\\017\\n\\n\\t\\t\\texamples (3rd alternation = escaped):\\n\\t\\t\\t?\\\\n      ?\\\\b\\n\\n\\t\\t\\texamples (4th alternation = meta-ctrl):\\n\\t\\t\\t?\\\\C-a    ?\\\\M-a    ?\\\\C-\\\\M-\\\\C-\\\\M-a\\n\\n\\t\\t\\texamples (4th alternation = normal):\\n\\t\\t\\t?a       ?A       ?0 \\n\\t\\t\\t?*       ?\\\"       ?( \\n\\t\\t\\t?.       ?#\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\tthe negative lookbehind prevents against matching\\n\\t\\t\\tp(42.tainted?)\\n\\t\\t\\t\",\n            \"match\":\n                \"(?<!\\\\w)\\\\?(\\\\\\\\(x\\\\h{1,2}(?!\\\\h)\\\\b|0[0-7]{0,2}(?![0-7])\\\\b|[^x0MC])|(\\\\\\\\[MC]-)+\\\\w|[^\\\\s\\\\\\\\])\",\n            \"name\": \"constant.numeric.ruby\"\n        },\n        {\n            \"begin\": \"^__END__\\\\n\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"string.unquoted.program-block.ruby\"\n                }\n            },\n            \"comment\": \"__END__ marker\",\n            \"contentName\": \"text.plain\",\n            \"end\": \"(?=not)impossible\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?=<?xml|<(?i:html\\\\b)|!DOCTYPE (?i:html\\\\b))\",\n                    \"end\": \"(?=not)impossible\",\n                    \"name\": \"text.html.embedded.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.basic\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)HTML)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded html\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.html\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)HTML)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"text.html\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"text.html.basic\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)XML)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded xml\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.xml\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)XML)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"text.xml\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"text.xml\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)SQL)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded sql\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.sql\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)SQL)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.sql\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.sql\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)CSS)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded css\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.css\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)CSS)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.css\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.css\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)CPP)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded c++\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.c++\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)CPP)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.c++\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.c++\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)C)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded c\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.c\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)C)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.c\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.c\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)(?:JS|JAVASCRIPT))\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded javascript\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.js\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)(?:JS|JAVASCRIPT))\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.js\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.js\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)JQUERY)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded jQuery javascript\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.js.jquery\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)JQUERY)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.js.jquery\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.js.jquery\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)(?:SH|SHELL))\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded shell\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.shell\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)(?:SH|SHELL))\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.shell\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.shell\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)LUA)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded lua\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.lua\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)LUA)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.lua\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.lua\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?=(?><<[-~](\\\"?)((?:[_\\\\w]+_|)RUBY)\\\\b\\\\1))\",\n            \"comment\": \"Heredoc with embedded ruby\",\n            \"end\": \"(?!\\\\G)\",\n            \"name\": \"meta.embedded.block.ruby\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?><<[-~](\\\"?)((?:[_\\\\w]+_|)RUBY)\\\\b\\\\1)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.ruby\",\n                    \"end\": \"\\\\s*\\\\2$\\\\n?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#heredoc\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        },\n                        {\n                            \"include\": \"source.ruby\"\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?>=\\\\s*<<(\\\\w+))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ruby\"\n                }\n            },\n            \"end\": \"^\\\\1$\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.ruby\"\n                }\n            },\n            \"name\": \"string.unquoted.heredoc.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"#heredoc\"\n                },\n                {\n                    \"include\": \"#interpolated_ruby\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?><<[-~](\\\\w+))\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ruby\"\n                }\n            },\n            \"comment\": \"heredoc with indented terminator\",\n            \"end\": \"\\\\s*\\\\1$\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.ruby\"\n                }\n            },\n            \"name\": \"string.unquoted.heredoc.ruby\",\n            \"patterns\": [\n                {\n                    \"include\": \"#heredoc\"\n                },\n                {\n                    \"include\": \"#interpolated_ruby\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                }\n            ]\n        },\n        {\n            \"begin\": \"(?<=\\\\{|do|\\\\{\\\\s|do\\\\s)(\\\\|)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.arguments.ruby\"\n                }\n            },\n            \"end\": \"(?<!\\\\|)(\\\\|)(?!\\\\|)\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                },\n                {\n                    \"match\": \"[_a-zA-Z][_a-zA-Z0-9]*\",\n                    \"name\": \"variable.other.block.ruby\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.variable.ruby\"\n                }\n            ]\n        },\n        {\n            \"match\": \"=>\",\n            \"name\": \"punctuation.separator.key-value\"\n        },\n        {\n            \"match\": \"->\",\n            \"name\": \"support.function.kernel.lambda.ruby\"\n        },\n        {\n            \"match\": \"<<=|%=|&{1,2}=|\\\\*=|\\\\*\\\\*=|\\\\+=|-=|\\\\^=|\\\\|{1,2}=|<<\",\n            \"name\": \"keyword.operator.assignment.augmented.ruby\"\n        },\n        {\n            \"match\": \"<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|(?<=[ \\\\t])\\\\?\",\n            \"name\": \"keyword.operator.comparison.ruby\"\n        },\n        {\n            \"match\": \"(?<!\\\\.)\\\\b(and|not|or)\\\\b(?![?!])\",\n            \"name\": \"keyword.operator.logical.ruby\"\n        },\n        {\n            \"comment\": \"Make sure this goes after assignment and comparison\",\n            \"match\": \"(?<=^|[ \\\\t])!|&&|\\\\|\\\\||\\\\^\",\n            \"name\": \"keyword.operator.logical.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.method.ruby\"\n                }\n            },\n            \"comment\": \"Safe navigation operator - Added in 2.3\",\n            \"match\": \"(&\\\\.)\\\\s*(?![A-Z])\"\n        },\n        {\n            \"match\": \"(%|&|\\\\*\\\\*|\\\\*|\\\\+|-|/)\",\n            \"name\": \"keyword.operator.arithmetic.ruby\"\n        },\n        {\n            \"match\": \"=\",\n            \"name\": \"keyword.operator.assignment.ruby\"\n        },\n        {\n            \"match\": \"\\\\||~|>>\",\n            \"name\": \"keyword.operator.other.ruby\"\n        },\n        {\n            \"match\": \";\",\n            \"name\": \"punctuation.separator.statement.ruby\"\n        },\n        {\n            \"match\": \",\",\n            \"name\": \"punctuation.separator.object.ruby\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.namespace.ruby\"\n                }\n            },\n            \"comment\": \"Mark as namespace separator if double colons followed by capital letter\",\n            \"match\": \"(::)\\\\s*(?=[A-Z])\"\n        },\n        {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.separator.method.ruby\"\n                }\n            },\n            \"comment\": \"Mark as method separator if double colons not followed by capital letter\",\n            \"match\": \"(\\\\.|::)\\\\s*(?![A-Z])\"\n        },\n        {\n            \"comment\": \"Must come after method and constant separators to prefer double colons\",\n            \"match\": \":\",\n            \"name\": \"punctuation.separator.other.ruby\"\n        },\n        {\n            \"match\": \"\\\\{\",\n            \"name\": \"punctuation.section.scope.begin.ruby\"\n        },\n        {\n            \"match\": \"\\\\}\",\n            \"name\": \"punctuation.section.scope.end.ruby\"\n        },\n        {\n            \"match\": \"\\\\[\",\n            \"name\": \"punctuation.section.array.begin.ruby\"\n        },\n        {\n            \"match\": \"\\\\]\",\n            \"name\": \"punctuation.section.array.end.ruby\"\n        },\n        {\n            \"match\": \"\\\\(|\\\\)\",\n            \"name\": \"punctuation.section.function.ruby\"\n        }\n    ],\n    \"repository\": {\n        \"escaped_char\": {\n            \"match\": \"\\\\\\\\(?:[0-7]{1,3}|x[\\\\da-fA-F]{1,2}|.)\",\n            \"name\": \"constant.character.escape.ruby\"\n        },\n        \"heredoc\": {\n            \"begin\": \"^<<[-~]?\\\\w+\",\n            \"end\": \"$\",\n            \"patterns\": [\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"interpolated_ruby\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"#\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.ruby\"\n                        }\n                    },\n                    \"contentName\": \"source.ruby\",\n                    \"end\": \"(\\\\})\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.ruby\"\n                        },\n                        \"1\": {\n                            \"name\": \"source.ruby\"\n                        }\n                    },\n                    \"name\": \"meta.embedded.line.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#nest_curly_and_self\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"nest_curly_and_self\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"punctuation.section.scope.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#nest_curly_and_self\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.ruby\"\n                        }\n                    },\n                    \"match\": \"(#@)[a-zA-Z_]\\\\w*\",\n                    \"name\": \"variable.other.readwrite.instance.ruby\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.ruby\"\n                        }\n                    },\n                    \"match\": \"(#@@)[a-zA-Z_]\\\\w*\",\n                    \"name\": \"variable.other.readwrite.class.ruby\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.ruby\"\n                        }\n                    },\n                    \"match\": \"(#\\\\$)[a-zA-Z_]\\\\w*\",\n                    \"name\": \"variable.other.readwrite.global.ruby\"\n                }\n            ]\n        },\n        \"percent_literals\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"%i(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.end.ruby\"\n                        }\n                    },\n                    \"name\": \"meta.array.symbol.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#symbol\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\<|\\\\\\\\>\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\{|\\\\\\\\\\\\}\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\[|\\\\\\\\\\\\]\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\(|\\\\\\\\\\\\)\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"symbol\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\\\\\|\\\\\\\\[ ]\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                },\n                                {\n                                    \"match\": \"\\\\S\\\\w*\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%I(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.end.ruby\"\n                        }\n                    },\n                    \"name\": \"meta.array.symbol.interpolated.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                },\n                                {\n                                    \"include\": \"#symbol\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#symbol\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"<\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.other.symbol.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        },\n                                        {\n                                            \"include\": \"#symbol\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"symbol\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"(?=\\\\\\\\|#\\\\{)\",\n                                    \"end\": \"(?!\\\\G)\",\n                                    \"name\": \"constant.other.symbol.ruby\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escaped_char\"\n                                        },\n                                        {\n                                            \"include\": \"#interpolated_ruby\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"match\": \"\\\\S\\\\w*\",\n                                    \"name\": \"constant.other.symbol.ruby\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%q(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.quoted.other.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                }\n                            ]\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\<|\\\\\\\\>|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\\\\{|\\\\\\\\\\\\}|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\\\\[|\\\\\\\\\\\\]|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\\\\(|\\\\\\\\\\\\)|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%Q?(?:([(\\\\[{<])|([^\\\\w\\\\s=]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.quoted.other.interpolated.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%r(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"([)\\\\]}>]\\\\2|\\\\1\\\\2)[eimnosux]*\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.regexp.percent.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#regex_sub\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#regex_sub\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#regex_sub\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#regex_sub\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#regex_sub\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%s(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.constant.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.constant.end.ruby\"\n                        }\n                    },\n                    \"name\": \"constant.other.symbol.percent.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                }\n                            ]\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\<|\\\\\\\\>|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\\\\{|\\\\\\\\\\\\}|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\\\\[|\\\\\\\\\\\\]|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\\\\\\\\\(|\\\\\\\\\\\\)|\\\\\\\\\\\\\\\\\",\n                                    \"name\": \"constant.character.escape.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%w(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.end.ruby\"\n                        }\n                    },\n                    \"name\": \"meta.array.string.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\<|\\\\\\\\>\",\n                                    \"name\": \"string.other.ruby\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\{|\\\\\\\\\\\\}\",\n                                    \"name\": \"string.other.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\[|\\\\\\\\\\\\]\",\n                                    \"name\": \"string.other.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\(|\\\\\\\\\\\\)\",\n                                    \"name\": \"string.other.ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"string\": {\n                            \"patterns\": [\n                                {\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"constant.character.escape.ruby\"\n                                        }\n                                    },\n                                    \"match\": \"\\\\\\\\\\\\\\\\|\\\\\\\\[ ]\",\n                                    \"name\": \"string.other.ruby\"\n                                },\n                                {\n                                    \"match\": \"\\\\S\\\\w*\",\n                                    \"name\": \"string.other.ruby\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%W(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.array.end.ruby\"\n                        }\n                    },\n                    \"name\": \"meta.array.string.interpolated.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"<\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"captures\": {\n                                        \"0\": {\n                                            \"name\": \"string.other.ruby\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        },\n                                        {\n                                            \"include\": \"#string\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"string\": {\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"(?=\\\\\\\\|#\\\\{)\",\n                                    \"end\": \"(?!\\\\G)\",\n                                    \"name\": \"string.other.ruby\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#escaped_char\"\n                                        },\n                                        {\n                                            \"include\": \"#interpolated_ruby\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"match\": \"\\\\S\\\\w*\",\n                                    \"name\": \"string.other.ruby\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"%x(?:([(\\\\[{<])|([^\\\\w\\\\s]|_))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"[)\\\\]}>]\\\\2|\\\\1\\\\2\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.ruby\"\n                        }\n                    },\n                    \"name\": \"string.interpolated.percent.ruby\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\()(?!\\\\))\",\n                            \"end\": \"(?=\\\\))\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#parens\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\[)(?!\\\\])\",\n                            \"end\": \"(?=\\\\])\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#brackets\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=\\\\{)(?!\\\\})\",\n                            \"end\": \"(?=\\\\})\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#braces\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"\\\\G(?<=<)(?!>)\",\n                            \"end\": \"(?=>)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#angles\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#escaped_char\"\n                        },\n                        {\n                            \"include\": \"#interpolated_ruby\"\n                        }\n                    ],\n                    \"repository\": {\n                        \"angles\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"<\",\n                                    \"end\": \">\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#angles\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"braces\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\{\",\n                                    \"end\": \"\\\\}\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#braces\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"brackets\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\[\",\n                                    \"end\": \"\\\\]\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#brackets\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        \"parens\": {\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#escaped_char\"\n                                },\n                                {\n                                    \"include\": \"#interpolated_ruby\"\n                                },\n                                {\n                                    \"begin\": \"\\\\(\",\n                                    \"end\": \"\\\\)\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#parens\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    }\n                }\n            ]\n        },\n        \"regex_sub\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#interpolated_ruby\"\n                },\n                {\n                    \"include\": \"#escaped_char\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.quantifier.begin.ruby\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.quantifier.end.ruby\"\n                        }\n                    },\n                    \"match\": \"(\\\\{)\\\\d+(,\\\\d+)?(\\\\})\",\n                    \"name\": \"keyword.operator.quantifier.ruby\"\n                },\n                {\n                    \"begin\": \"\\\\[\\\\^?\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.character-class.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.character-class.end.ruby\"\n                        }\n                    },\n                    \"name\": \"constant.other.character-class.set.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\(\\\\?#\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.begin.ruby\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.end.ruby\"\n                        }\n                    },\n                    \"name\": \"comment.line.number-sign.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#escaped_char\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.ruby\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"name\": \"meta.group.regexp.ruby\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regex_sub\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|\\\\s)(#)\\\\s(?=[[a-zA-Z0-9,. \\\\t?!-][^\\\\x{00}-\\\\x{7F}]]*$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.ruby\"\n                        }\n                    },\n                    \"comment\":\n                        \"We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.\",\n                    \"end\": \"$\\\\n?\",\n                    \"name\": \"comment.line.number-sign.ruby\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/rust/syntaxes/rust.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/zargony/atom-language-rust/blob/master/grammars/rust.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/zargony/atom-language-rust/commit/179f449a69182cae4fcdf644d59d842b7e445f89\",\n    \"name\": \"Rust\",\n    \"scopeName\": \"source.rust\",\n    \"patterns\": [\n        {\n            \"comment\": \"Implementation\",\n            \"begin\": \"\\\\b(impl)\\\\b\",\n            \"end\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.rust\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#block_comment\"\n                },\n                {\n                    \"include\": \"#line_comment\"\n                },\n                {\n                    \"include\": \"#sigils\"\n                },\n                {\n                    \"include\": \"#mut\"\n                },\n                {\n                    \"include\": \"#ref_lifetime\"\n                },\n                {\n                    \"include\": \"#core_types\"\n                },\n                {\n                    \"include\": \"#core_marker\"\n                },\n                {\n                    \"include\": \"#core_traits\"\n                },\n                {\n                    \"include\": \"#std_types\"\n                },\n                {\n                    \"include\": \"#std_traits\"\n                },\n                {\n                    \"include\": \"#type_params\"\n                },\n                {\n                    \"include\": \"#where\"\n                },\n                {\n                    \"name\": \"storage.type.rust\",\n                    \"match\": \"\\\\bfor\\\\b\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        {\n            \"include\": \"#block_doc_comment\"\n        },\n        {\n            \"include\": \"#block_comment\"\n        },\n        {\n            \"include\": \"#line_doc_comment\"\n        },\n        {\n            \"include\": \"#line_comment\"\n        },\n        {\n            \"comment\": \"Attribute\",\n            \"name\": \"meta.attribute.rust\",\n            \"begin\": \"#\\\\!?\\\\[\",\n            \"end\": \"\\\\]\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string_literal\"\n                },\n                {\n                    \"include\": \"#block_doc_comment\"\n                },\n                {\n                    \"include\": \"#block_comment\"\n                },\n                {\n                    \"include\": \"#line_doc_comment\"\n                },\n                {\n                    \"include\": \"#line_comment\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Single-quote string literal (character)\",\n            \"name\": \"string.quoted.single.rust\",\n            \"match\":\n                \"b?'([^'\\\\\\\\]|\\\\\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.))'\"\n        },\n        {\n            \"include\": \"#string_literal\"\n        },\n        {\n            \"include\": \"#raw_string_literal\"\n        },\n        {\n            \"comment\": \"Floating point literal (fraction)\",\n            \"name\": \"constant.numeric.float.rust\",\n            \"match\": \"\\\\b[0-9][0-9_]*\\\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?(f32|f64)?\\\\b\"\n        },\n        {\n            \"comment\": \"Floating point literal (exponent)\",\n            \"name\": \"constant.numeric.float.rust\",\n            \"match\": \"\\\\b[0-9][0-9_]*(\\\\.[0-9][0-9_]*)?[eE][+-]?[0-9_]+(f32|f64)?\\\\b\"\n        },\n        {\n            \"comment\": \"Floating point literal (typed)\",\n            \"name\": \"constant.numeric.float.rust\",\n            \"match\": \"\\\\b[0-9][0-9_]*(\\\\.[0-9][0-9_]*)?([eE][+-]?[0-9_]+)?(f32|f64)\\\\b\"\n        },\n        {\n            \"comment\": \"Integer literal (decimal)\",\n            \"name\": \"constant.numeric.integer.decimal.rust\",\n            \"match\": \"\\\\b[0-9][0-9_]*([ui](8|16|32|64|128|s|size))?\\\\b\"\n        },\n        {\n            \"comment\": \"Integer literal (hexadecimal)\",\n            \"name\": \"constant.numeric.integer.hexadecimal.rust\",\n            \"match\": \"\\\\b0x[a-fA-F0-9_]+([ui](8|16|32|64|128|s|size))?\\\\b\"\n        },\n        {\n            \"comment\": \"Integer literal (octal)\",\n            \"name\": \"constant.numeric.integer.octal.rust\",\n            \"match\": \"\\\\b0o[0-7_]+([ui](8|16|32|64|128|s|size))?\\\\b\"\n        },\n        {\n            \"comment\": \"Integer literal (binary)\",\n            \"name\": \"constant.numeric.integer.binary.rust\",\n            \"match\": \"\\\\b0b[01_]+([ui](8|16|32|64|128|s|size))?\\\\b\"\n        },\n        {\n            \"comment\": \"Static storage modifier\",\n            \"name\": \"storage.modifier.static.rust\",\n            \"match\": \"\\\\bstatic\\\\b\"\n        },\n        {\n            \"comment\": \"Boolean constant\",\n            \"name\": \"constant.language.boolean.rust\",\n            \"match\": \"\\\\b(true|false)\\\\b\"\n        },\n        {\n            \"comment\": \"Control keyword\",\n            \"name\": \"keyword.control.rust\",\n            \"match\": \"\\\\b(break|continue|else|if|in|for|loop|match|return|while)\\\\b\"\n        },\n        {\n            \"comment\": \"Keyword\",\n            \"name\": \"keyword.other.rust\",\n            \"match\": \"\\\\b(crate|extern|mod|let|ref|use|super|move)\\\\b\"\n        },\n        {\n            \"comment\": \"Reserved keyword\",\n            \"name\": \"invalid.deprecated.rust\",\n            \"match\":\n                \"\\\\b(abstract|alignof|become|do|final|macro|offsetof|override|priv|proc|pure|sizeof|typeof|virtual|yield)\\\\b\"\n        },\n        {\n            \"include\": \"#unsafe\"\n        },\n        {\n            \"include\": \"#sigils\"\n        },\n        {\n            \"include\": \"#self\"\n        },\n        {\n            \"include\": \"#mut\"\n        },\n        {\n            \"include\": \"#box\"\n        },\n        {\n            \"include\": \"#lifetime\"\n        },\n        {\n            \"include\": \"#ref_lifetime\"\n        },\n        {\n            \"include\": \"#const\"\n        },\n        {\n            \"include\": \"#pub\"\n        },\n        {\n            \"comment\": \"Miscellaneous operator\",\n            \"name\": \"keyword.operator.misc.rust\",\n            \"match\": \"(=>|::|\\\\bas\\\\b)\"\n        },\n        {\n            \"comment\": \"Comparison operator\",\n            \"name\": \"keyword.operator.comparison.rust\",\n            \"match\": \"(&&|\\\\|\\\\||==|!=)\"\n        },\n        {\n            \"comment\": \"Assignment operator\",\n            \"name\": \"keyword.operator.assignment.rust\",\n            \"match\": \"(\\\\+=|-=|/=|\\\\*=|%=|\\\\^=|&=|\\\\|=|<<=|>>=|=)\"\n        },\n        {\n            \"comment\": \"Arithmetic operator\",\n            \"name\": \"keyword.operator.arithmetic.rust\",\n            \"match\": \"(!|\\\\+|-|/|\\\\*|%|\\\\^|&|\\\\||<<|>>)\"\n        },\n        {\n            \"comment\": \"Comparison operator (second group because of regex precedence)\",\n            \"name\": \"keyword.operator.comparison.rust\",\n            \"match\": \"(<=|>=|<|>)\"\n        },\n        {\n            \"include\": \"#core_types\"\n        },\n        {\n            \"include\": \"#core_vars\"\n        },\n        {\n            \"include\": \"#core_marker\"\n        },\n        {\n            \"include\": \"#core_traits\"\n        },\n        {\n            \"include\": \"#std_types\"\n        },\n        {\n            \"include\": \"#std_traits\"\n        },\n        {\n            \"comment\": \"Built-in macro\",\n            \"name\": \"support.function.builtin.rust\",\n            \"match\":\n                \"\\\\b(macro_rules|compile_error|format_args|env|option_env|concat_idents|concat|line|column|file|stringify|include|include_str|include_bytes|module_path|cfg)!\"\n        },\n        {\n            \"comment\": \"Core macro\",\n            \"name\": \"support.function.core.rust\",\n            \"match\":\n                \"\\\\b(panic|assert|assert_eq|assert_ne|debug_assert|debug_assert_eq|debug_assert_ne|try|write|writeln|unreachable|unimplemented)!\"\n        },\n        {\n            \"comment\": \"Standard library macro\",\n            \"name\": \"support.function.std.rust\",\n            \"match\": \"\\\\b(format|print|println|eprint|eprintln|select|vec)!\"\n        },\n        {\n            \"comment\": \"Logging macro\",\n            \"name\": \"support.function.log.rust\",\n            \"match\": \"\\\\b(log|error|warn|info|debug|trace|log_enabled)!\"\n        },\n        {\n            \"comment\": \"Invokation of a macro\",\n            \"match\": \"\\\\b([a-zA-Z_][a-zA-Z0-9_]*\\\\!)\\\\s*[({\\\\[]\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.macro.rust\"\n                }\n            }\n        },\n        {\n            \"comment\": \"Function call\",\n            \"match\": \"\\\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\\\s*\\\\(\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.rust\"\n                }\n            }\n        },\n        {\n            \"comment\": \"Function call with type parameters\",\n            \"begin\": \"\\\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\\\s*(::)(?=\\\\s*<.*>\\\\s*\\\\()\",\n            \"end\": \"\\\\(\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.rust\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.misc.rust\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type_params\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Function definition\",\n            \"begin\": \"\\\\b(fn)\\\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\",\n            \"end\": \"[\\\\{;]\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.other.fn.rust\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.function.rust\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#block_comment\"\n                },\n                {\n                    \"include\": \"#line_comment\"\n                },\n                {\n                    \"include\": \"#sigils\"\n                },\n                {\n                    \"include\": \"#self\"\n                },\n                {\n                    \"include\": \"#mut\"\n                },\n                {\n                    \"include\": \"#ref_lifetime\"\n                },\n                {\n                    \"include\": \"#core_types\"\n                },\n                {\n                    \"include\": \"#core_marker\"\n                },\n                {\n                    \"include\": \"#core_traits\"\n                },\n                {\n                    \"include\": \"#std_types\"\n                },\n                {\n                    \"include\": \"#std_traits\"\n                },\n                {\n                    \"include\": \"#type_params\"\n                },\n                {\n                    \"include\": \"#const\"\n                },\n                {\n                    \"include\": \"#where\"\n                },\n                {\n                    \"include\": \"#unsafe\"\n                },\n                {\n                    \"comment\": \"Function arguments\",\n                    \"match\": \"\\bfn\\b\",\n                    \"name\": \"keyword.other.fn.rust\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Type declaration\",\n            \"begin\": \"\\\\b(enum|struct|trait|union)\\\\s+([a-zA-Z_][a-zA-Z0-9_]*)\",\n            \"end\": \"[\\\\{\\\\(;]\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.rust\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.rust\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#block_comment\"\n                },\n                {\n                    \"include\": \"#line_comment\"\n                },\n                {\n                    \"include\": \"#core_traits\"\n                },\n                {\n                    \"include\": \"#std_traits\"\n                },\n                {\n                    \"include\": \"#type_params\"\n                },\n                {\n                    \"include\": \"#core_types\"\n                },\n                {\n                    \"include\": \"#pub\"\n                },\n                {\n                    \"include\": \"#where\"\n                }\n            ]\n        },\n        {\n            \"comment\": \"Type alias\",\n            \"begin\": \"\\\\b(type)\\\\s+([a-zA-Z_][a-zA-Z0-9_]*)\",\n            \"end\": \";\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.rust\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.type.rust\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#block_comment\"\n                },\n                {\n                    \"include\": \"#line_comment\"\n                },\n                {\n                    \"include\": \"#sigils\"\n                },\n                {\n                    \"include\": \"#mut\"\n                },\n                {\n                    \"include\": \"#lifetime\"\n                },\n                {\n                    \"include\": \"#ref_lifetime\"\n                },\n                {\n                    \"include\": \"#core_types\"\n                },\n                {\n                    \"include\": \"#core_marker\"\n                },\n                {\n                    \"include\": \"#core_traits\"\n                },\n                {\n                    \"include\": \"#std_types\"\n                },\n                {\n                    \"include\": \"#std_traits\"\n                },\n                {\n                    \"include\": \"#type_params\"\n                }\n            ]\n        }\n    ],\n    \"repository\": {\n        \"block_doc_comment\": {\n            \"comment\": \"Block documentation comment\",\n            \"name\": \"comment.block.documentation.rust\",\n            \"begin\": \"/\\\\*[\\\\*!](?![\\\\*/])\",\n            \"end\": \"\\\\*/\",\n            \"patterns\": [\n                {\n                    \"include\": \"#block_doc_comment\"\n                },\n                {\n                    \"include\": \"#block_comment\"\n                }\n            ]\n        },\n        \"block_comment\": {\n            \"comment\": \"Block comment\",\n            \"name\": \"comment.block.rust\",\n            \"begin\": \"/\\\\*\",\n            \"end\": \"\\\\*/\",\n            \"patterns\": [\n                {\n                    \"include\": \"#block_doc_comment\"\n                },\n                {\n                    \"include\": \"#block_comment\"\n                }\n            ]\n        },\n        \"line_doc_comment\": {\n            \"comment\": \"Single-line documentation comment\",\n            \"name\": \"comment.line.documentation.rust\",\n            \"begin\": \"//[!/](?=[^/])\",\n            \"end\": \"$\"\n        },\n        \"line_comment\": {\n            \"comment\": \"Single-line comment\",\n            \"name\": \"comment.line.double-slash.rust\",\n            \"begin\": \"//\",\n            \"end\": \"$\"\n        },\n        \"escaped_character\": {\n            \"name\": \"constant.character.escape.rust\",\n            \"match\": \"\\\\\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)\"\n        },\n        \"string_literal\": {\n            \"comment\": \"Double-quote string literal\",\n            \"name\": \"string.quoted.double.rust\",\n            \"begin\": \"b?\\\"\",\n            \"end\": \"\\\"\",\n            \"patterns\": [\n                {\n                    \"include\": \"#escaped_character\"\n                }\n            ]\n        },\n        \"raw_string_literal\": {\n            \"comment\": \"Raw double-quote string literal\",\n            \"name\": \"string.quoted.double.raw.rust\",\n            \"begin\": \"b?r(#*)\\\"\",\n            \"end\": \"\\\"\\\\1\"\n        },\n        \"sigils\": {\n            \"comment\": \"Sigil\",\n            \"name\": \"keyword.operator.sigil.rust\",\n            \"match\": \"[&*](?=[a-zA-Z0-9_\\\\(\\\\[\\\\|\\\\\\\"]+)\"\n        },\n        \"self\": {\n            \"comment\": \"Self variable\",\n            \"name\": \"variable.language.rust\",\n            \"match\": \"\\\\bself\\\\b\"\n        },\n        \"mut\": {\n            \"comment\": \"Mutable storage modifier\",\n            \"name\": \"storage.modifier.mut.rust\",\n            \"match\": \"\\\\bmut\\\\b\"\n        },\n        \"box\": {\n            \"comment\": \"Box storage modifier\",\n            \"name\": \"storage.modifier.box.rust\",\n            \"match\": \"\\\\bbox\\\\b\"\n        },\n        \"const\": {\n            \"comment\": \"Const storage modifier\",\n            \"name\": \"storage.modifier.const.rust\",\n            \"match\": \"\\\\bconst\\\\b\"\n        },\n        \"pub\": {\n            \"comment\": \"Visibility modifier\",\n            \"name\": \"storage.modifier.visibility.rust\",\n            \"match\": \"\\\\bpub\\\\b\"\n        },\n        \"unsafe\": {\n            \"comment\": \"Unsafe code keyword\",\n            \"name\": \"keyword.other.unsafe.rust\",\n            \"match\": \"\\\\bunsafe\\\\b\"\n        },\n        \"where\": {\n            \"comment\": \"Generic where clause\",\n            \"name\": \"keyword.other.where.rust\",\n            \"match\": \"\\\\bwhere\\\\b\"\n        },\n        \"lifetime\": {\n            \"comment\": \"Named lifetime\",\n            \"name\": \"storage.modifier.lifetime.rust\",\n            \"match\": \"'([a-zA-Z_][a-zA-Z0-9_]*)\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.name.lifetime.rust\"\n                }\n            }\n        },\n        \"ref_lifetime\": {\n            \"comment\": \"Reference with named lifetime\",\n            \"match\": \"&('([a-zA-Z_][a-zA-Z0-9_]*))\\\\b\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.lifetime.rust\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.lifetime.rust\"\n                }\n            }\n        },\n        \"core_types\": {\n            \"comment\": \"Built-in/core type\",\n            \"name\": \"storage.type.core.rust\",\n            \"match\":\n                \"\\\\b(bool|char|usize|isize|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|f32|f64|str|Self|Option|Result)\\\\b\"\n        },\n        \"core_vars\": {\n            \"comment\": \"Core type variant\",\n            \"name\": \"support.constant.core.rust\",\n            \"match\": \"\\\\b(Some|None|Ok|Err)\\\\b\"\n        },\n        \"core_marker\": {\n            \"comment\": \"Core trait (marker)\",\n            \"name\": \"support.type.marker.rust\",\n            \"match\": \"\\\\b(Copy|Send|Sized|Sync)\\\\b\"\n        },\n        \"core_traits\": {\n            \"comment\": \"Core trait\",\n            \"name\": \"support.type.core.rust\",\n            \"match\":\n                \"\\\\b(Drop|Fn|FnMut|FnOnce|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator)\\\\b\"\n        },\n        \"std_types\": {\n            \"comment\": \"Standard library type\",\n            \"name\": \"storage.class.std.rust\",\n            \"match\": \"\\\\b(Box|String|Vec|Path|PathBuf)\\\\b\"\n        },\n        \"std_traits\": {\n            \"comment\": \"Standard library trait\",\n            \"name\": \"support.type.std.rust\",\n            \"match\": \"\\\\b(ToOwned|ToString)\\\\b\"\n        },\n        \"type\": {\n            \"comment\": \"A type\",\n            \"name\": \"entity.name.type.rust\",\n            \"match\": \"\\\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\\\b\"\n        },\n        \"type_params\": {\n            \"comment\": \"Type parameters\",\n            \"name\": \"meta.type_params.rust\",\n            \"begin\": \"<(?![=<])\",\n            \"end\": \"(?<![-])>\",\n            \"patterns\": [\n                {\n                    \"include\": \"#block_comment\"\n                },\n                {\n                    \"include\": \"#line_comment\"\n                },\n                {\n                    \"include\": \"#sigils\"\n                },\n                {\n                    \"include\": \"#mut\"\n                },\n                {\n                    \"include\": \"#lifetime\"\n                },\n                {\n                    \"include\": \"#core_types\"\n                },\n                {\n                    \"include\": \"#core_marker\"\n                },\n                {\n                    \"include\": \"#core_traits\"\n                },\n                {\n                    \"include\": \"#std_types\"\n                },\n                {\n                    \"include\": \"#std_traits\"\n                },\n                {\n                    \"include\": \"#type_params\"\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/scss/syntaxes/scss.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-sass/blob/master/grammars/scss.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-sass/commit/a07688bd078f420f56df6221e9263d80e738869b\",\n    \"scopeName\": \"source.css.scss\",\n    \"name\": \"SCSS\",\n    \"fileTypes\": [\"scss\", \"css.scss\", \"css.scss.erb\", \"scss.erb\", \"scss.liquid\"],\n    \"patterns\": [\n        {\n            \"include\": \"#variable_setting\"\n        },\n        {\n            \"include\": \"#at_rule_include\"\n        },\n        {\n            \"include\": \"#at_rule_import\"\n        },\n        {\n            \"include\": \"#general\"\n        },\n        {\n            \"include\": \"#flow_control\"\n        },\n        {\n            \"include\": \"#rules\"\n        },\n        {\n            \"include\": \"#property_list\"\n        },\n        {\n            \"include\": \"#at_rule_mixin\"\n        },\n        {\n            \"include\": \"#at_rule_media\"\n        },\n        {\n            \"include\": \"#at_rule_function\"\n        },\n        {\n            \"include\": \"#at_rule_charset\"\n        },\n        {\n            \"include\": \"#at_rule_option\"\n        },\n        {\n            \"include\": \"#at_rule_namespace\"\n        },\n        {\n            \"include\": \"#at_rule_fontface\"\n        },\n        {\n            \"include\": \"#at_rule_page\"\n        },\n        {\n            \"include\": \"#at_rule_keyframes\"\n        },\n        {\n            \"include\": \"#at_rule_at_root\"\n        },\n        {\n            \"include\": \"#at_rule_supports\"\n        },\n        {\n            \"match\": \";\",\n            \"name\": \"punctuation.terminator.rule.css\"\n        }\n    ],\n    \"repository\": {\n        \"at_rule_charset\": {\n            \"begin\": \"\\\\s*((@)charset\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.charset.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*((?=;|$))\",\n            \"name\": \"meta.at-rule.charset.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#string_single\"\n                },\n                {\n                    \"include\": \"#string_double\"\n                }\n            ]\n        },\n        \"at_rule_content\": {\n            \"begin\": \"\\\\s*((@)content\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.content.scss\"\n                }\n            },\n            \"end\": \"\\\\s*((?=;))\",\n            \"name\": \"meta.content.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#selectors\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                }\n            ]\n        },\n        \"at_rule_each\": {\n            \"begin\": \"\\\\s*((@)each\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.each.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*((?=}))\",\n            \"name\": \"meta.at-rule.each.scss\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\b(in|,)\\\\b\",\n                    \"name\": \"keyword.control.operator\"\n                },\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"at_rule_else\": {\n            \"begin\": \"\\\\s*((@)else(\\\\s*(if)?))\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.else.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*(?={)\",\n            \"name\": \"meta.at-rule.else.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#conditional_operators\"\n                },\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                }\n            ]\n        },\n        \"at_rule_extend\": {\n            \"begin\": \"\\\\s*((@)extend\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.extend.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*(?=;)\",\n            \"name\": \"meta.at-rule.extend.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#selectors\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                }\n            ]\n        },\n        \"at_rule_fontface\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*((@)font-face\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.fontface.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\s*(?={)\",\n                    \"name\": \"meta.at-rule.fontface.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function_attributes\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"at_rule_for\": {\n            \"begin\": \"\\\\s*((@)for\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.for.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*(?={)\",\n            \"name\": \"meta.at-rule.for.scss\",\n            \"patterns\": [\n                {\n                    \"match\": \"(==|!=|<=|>=|<|>|from|to|through)\",\n                    \"name\": \"keyword.control.operator\"\n                },\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"at_rule_function\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\s*((@)function\\\\b)\\\\s*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.function.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\s*(?={)\",\n                    \"name\": \"meta.at-rule.function.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function_attributes\"\n                        }\n                    ]\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.function.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.scss\"\n                        }\n                    },\n                    \"match\": \"\\\\s*((@)function\\\\b)\\\\s*\",\n                    \"name\": \"meta.at-rule.function.scss\"\n                }\n            ]\n        },\n        \"at_rule_if\": {\n            \"begin\": \"\\\\s*((@)if\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.if.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*(?={)\",\n            \"name\": \"meta.at-rule.if.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#conditional_operators\"\n                },\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                }\n            ]\n        },\n        \"at_rule_import\": {\n            \"begin\": \"\\\\s*((@)import\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.import.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*((?=;)|(?=}))\",\n            \"name\": \"meta.at-rule.import.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#string_single\"\n                },\n                {\n                    \"include\": \"#string_double\"\n                },\n                {\n                    \"include\": \"#functions\"\n                },\n                {\n                    \"include\": \"#comment_line\"\n                }\n            ]\n        },\n        \"at_rule_include\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=@include)\\\\s+([\\\\w-]+)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.parameters.begin.bracket.round.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.end.bracket.round.scss\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.include.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function_attributes\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(?<=@include)\\\\s+([\\\\w-]+)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.at-rule.include.scss\"\n                        },\n                        \"1\": {\n                            \"name\": \"entity.name.function.scss\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"((@)include)\\\\b\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.at-rule.include.scss\"\n                        },\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.include.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"at_rule_keyframes\": {\n            \"begin\": \"(?<=^|\\\\s)(@)(?:-(?:webkit|moz)-)?keyframes\\\\b\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.control.at-rule.keyframes.scss\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"(?<=})\",\n            \"name\": \"meta.at-rule.keyframes.scss\",\n            \"patterns\": [\n                {\n                    \"match\": \"(?<=@keyframes)\\\\s+((?:[_A-Za-z][-\\\\w]|-[_A-Za-z])[-\\\\w]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.scss\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(?<=@keyframes)\\\\s+(\\\")\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.scss\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.scss\"\n                        }\n                    },\n                    \"name\": \"string.quoted.double.scss\",\n                    \"contentName\": \"entity.name.function.scss\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\(\\\\h{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"include\": \"#interpolation\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=@keyframes)\\\\s+(')\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.scss\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.scss\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.scss\",\n                    \"contentName\": \"entity.name.function.scss\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\(\\\\h{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"include\": \"#interpolation\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.keyframes.begin.scss\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.keyframes.end.scss\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\b(?:(?:100|[1-9]\\\\d|\\\\d)%|from|to)(?=\\\\s*{)\",\n                            \"name\": \"entity.other.attribute-name.scss\"\n                        },\n                        {\n                            \"include\": \"#flow_control\"\n                        },\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"include\": \"#property_list\"\n                        },\n                        {\n                            \"include\": \"#rules\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"at_rule_media\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*((@)media)\\\\b\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.media.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\s*(?={)\",\n                    \"name\": \"meta.at-rule.media.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment_block\"\n                        },\n                        {\n                            \"include\": \"#comment_line\"\n                        },\n                        {\n                            \"match\": \"\\\\b(only)\\\\b\",\n                            \"name\": \"keyword.control.operator.css.scss\"\n                        },\n                        {\n                            \"begin\": \"\\\\(\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.media-query.begin.bracket.round.scss\"\n                                }\n                            },\n                            \"end\": \"\\\\)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\":\n                                        \"punctuation.definition.media-query.end.bracket.round.scss\"\n                                }\n                            },\n                            \"name\": \"meta.property-list.media-query.scss\",\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"(?<![-a-z])(?=[-a-z])\",\n                                    \"end\": \"$|(?![-a-z])\",\n                                    \"name\": \"meta.property-name.media-query.scss\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"source.css#media-features\"\n                                        },\n                                        {\n                                            \"include\": \"source.css#property-names\"\n                                        }\n                                    ]\n                                },\n                                {\n                                    \"begin\": \"(:)\\\\s*(?!(\\\\s*{))\",\n                                    \"beginCaptures\": {\n                                        \"1\": {\n                                            \"name\": \"punctuation.separator.key-value.scss\"\n                                        }\n                                    },\n                                    \"end\": \"\\\\s*(;|(?=}|\\\\)))\",\n                                    \"endCaptures\": {\n                                        \"1\": {\n                                            \"name\": \"punctuation.terminator.rule.scss\"\n                                        }\n                                    },\n                                    \"contentName\": \"meta.property-value.media-query.scss\",\n                                    \"patterns\": [\n                                        {\n                                            \"include\": \"#general\"\n                                        },\n                                        {\n                                            \"include\": \"#property_values\"\n                                        }\n                                    ]\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#variable\"\n                        },\n                        {\n                            \"include\": \"#conditional_operators\"\n                        },\n                        {\n                            \"include\": \"source.css#media-types\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"at_rule_mixin\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=@mixin)\\\\s+([\\\\w-]+)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.parameters.begin.bracket.round.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.parameters.end.bracket.round.scss\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.mixin.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function_attributes\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(?<=@mixin)\\\\s+([\\\\w-]+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.scss\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.mixin.scss\"\n                },\n                {\n                    \"match\": \"((@)mixin)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.mixin.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.mixin.scss\"\n                }\n            ]\n        },\n        \"at_rule_namespace\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=@namespace)\\\\s+(?=url)\",\n                    \"end\": \"(?=;|$)\",\n                    \"name\": \"meta.at-rule.namespace.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#property_values\"\n                        },\n                        {\n                            \"include\": \"#string_single\"\n                        },\n                        {\n                            \"include\": \"#string_double\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=@namespace)\\\\s+([\\\\w-]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.namespace-prefix.scss\"\n                        }\n                    },\n                    \"end\": \"(?=;|$)\",\n                    \"name\": \"meta.at-rule.namespace.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#variables\"\n                        },\n                        {\n                            \"include\": \"#property_values\"\n                        },\n                        {\n                            \"include\": \"#string_single\"\n                        },\n                        {\n                            \"include\": \"#string_double\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"((@)namespace)\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.namespace.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        }\n                    },\n                    \"name\": \"meta.at-rule.namespace.scss\"\n                }\n            ]\n        },\n        \"at_rule_option\": {\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.charset.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"match\": \"^\\\\s*((@)option\\\\b)\\\\s*\",\n            \"name\": \"meta.at-rule.option.scss\"\n        },\n        \"at_rule_page\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"^\\\\s*((@)page)(?=:|\\\\s)\\\\s*([-:\\\\w]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.at-rule.page.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.keyword.scss\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\s*(?={)\",\n                    \"name\": \"meta.at-rule.page.scss\"\n                }\n            ]\n        },\n        \"at_rule_return\": {\n            \"begin\": \"\\\\s*((@)(return)\\\\b)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.return.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*((?=;))\",\n            \"name\": \"meta.at-rule.return.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                }\n            ]\n        },\n        \"at_rule_at_root\": {\n            \"begin\": \"\\\\s*((@)(at-root))(\\\\s+|$)\",\n            \"end\": \"\\\\s*(?={)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.at-rule.at-root.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"name\": \"meta.at-rule.at-root.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function_attributes\"\n                },\n                {\n                    \"include\": \"#functions\"\n                },\n                {\n                    \"include\": \"#selectors\"\n                }\n            ]\n        },\n        \"at_rule_supports\": {\n            \"begin\": \"(?<=^|\\\\s)(@)supports\\\\b\",\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"keyword.control.at-rule.supports.scss\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"(?={)|$\",\n            \"name\": \"meta.at-rule.supports.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#logical_operators\"\n                },\n                {\n                    \"include\": \"#properties\"\n                },\n                {\n                    \"match\": \"\\\\(\",\n                    \"name\": \"punctuation.definition.condition.begin.bracket.round.scss\"\n                },\n                {\n                    \"match\": \"\\\\)\",\n                    \"name\": \"punctuation.definition.condition.end.bracket.round.scss\"\n                }\n            ]\n        },\n        \"at_rule_warn\": {\n            \"begin\": \"\\\\s*((@)(warn|debug|error)\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.warn.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*(?=;)\",\n            \"name\": \"meta.at-rule.warn.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#string_double\"\n                },\n                {\n                    \"include\": \"#string_single\"\n                }\n            ]\n        },\n        \"at_rule_while\": {\n            \"begin\": \"\\\\s*((@)while\\\\b)\\\\s*\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.while.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.keyword.scss\"\n                }\n            },\n            \"end\": \"\\\\s*(?=})\",\n            \"name\": \"meta.at-rule.while.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#conditional_operators\"\n                },\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"comment_block\": {\n            \"begin\": \"/\\\\*\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.scss\"\n                }\n            },\n            \"end\": \"\\\\*/\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.scss\"\n                }\n            },\n            \"name\": \"comment.block.scss\"\n        },\n        \"comment_line\": {\n            \"begin\": \"//\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.scss\"\n                }\n            },\n            \"end\": \"\\\\n\",\n            \"name\": \"comment.line.scss\"\n        },\n        \"constant_default\": {\n            \"match\": \"!default\",\n            \"name\": \"keyword.other.default.scss\"\n        },\n        \"constant_functions\": {\n            \"begin\": \"([\\\\w-]+)(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"support.function.misc.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.function.scss\"\n                }\n            },\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.function.scss\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameters\"\n                }\n            ]\n        },\n        \"constant_important\": {\n            \"match\": \"!important\",\n            \"name\": \"keyword.other.important.scss\"\n        },\n        \"constant_mathematical_symbols\": {\n            \"match\": \"\\\\b(\\\\+|-|\\\\*|/)\\\\b\",\n            \"name\": \"support.constant.mathematical-symbols.scss\"\n        },\n        \"constant_optional\": {\n            \"match\": \"!optional\",\n            \"name\": \"keyword.other.optional.scss\"\n        },\n        \"constant_sass_functions\": {\n            \"begin\":\n                \"(headings|stylesheet-url|rgba?|hsla?|ie-hex-str|red|green|blue|alpha|opacity|hue|saturation|lightness|prefixed|prefix|-moz|-svg|-css2|-pie|-webkit|-ms|font-(?:files|url)|grid-image|image-(?:width|height|url|color)|sprites?|sprite-(?:map|map-name|file|url|position)|inline-(?:font-files|image)|opposite-position|grad-point|grad-end-position|color-stops|color-stops-in-percentages|grad-color-stops|(?:radial|linear)-(?:gradient|svg-gradient)|opacify|fade-?in|transparentize|fade-?out|lighten|darken|saturate|desaturate|grayscale|adjust-(?:hue|lightness|saturation|color)|scale-(?:lightness|saturation|color)|change-color|spin|complement|invert|mix|-compass-(?:list|space-list|slice|nth|list-size)|blank|compact|nth|first-value-of|join|length|append|nest|append-selector|headers|enumerate|range|percentage|unitless|unit|if|type-of|comparable|elements-of-type|quote|unquote|escape|e|sin|cos|tan|abs|round|ceil|floor|pi|translate(?:X|Y))(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"support.function.misc.scss\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.section.function.scss\"\n                }\n            },\n            \"end\": \"(\\\\))\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.section.function.scss\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameters\"\n                }\n            ]\n        },\n        \"flow_control\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#at_rule_if\"\n                },\n                {\n                    \"include\": \"#at_rule_else\"\n                },\n                {\n                    \"include\": \"#at_rule_warn\"\n                },\n                {\n                    \"include\": \"#at_rule_for\"\n                },\n                {\n                    \"include\": \"#at_rule_while\"\n                },\n                {\n                    \"include\": \"#at_rule_each\"\n                },\n                {\n                    \"include\": \"#at_rule_return\"\n                }\n            ]\n        },\n        \"function_attributes\": {\n            \"patterns\": [\n                {\n                    \"match\": \":\",\n                    \"name\": \"punctuation.separator.key-value.scss\"\n                },\n                {\n                    \"include\": \"#general\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"match\": \"[={}\\\\?;@]\",\n                    \"name\": \"invalid.illegal.scss\"\n                }\n            ]\n        },\n        \"functions\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"([\\\\w-]{1,})(\\\\()\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"support.function.misc.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.section.function.scss\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.section.function.scss\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameters\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"([\\\\w-]{1,})\",\n                    \"name\": \"support.function.misc.scss\"\n                }\n            ]\n        },\n        \"general\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"include\": \"#comment_block\"\n                },\n                {\n                    \"include\": \"#comment_line\"\n                }\n            ]\n        },\n        \"interpolation\": {\n            \"begin\": \"#{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.interpolation.begin.bracket.curly.scss\"\n                }\n            },\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.interpolation.end.bracket.curly.scss\"\n                }\n            },\n            \"name\": \"variable.interpolation.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"#variable\"\n                }\n            ]\n        },\n        \"conditional_operators\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comparison_operators\"\n                },\n                {\n                    \"include\": \"#logical_operators\"\n                }\n            ]\n        },\n        \"comparison_operators\": {\n            \"match\": \"==|!=|<=|>=|<|>\",\n            \"name\": \"keyword.operator.comparison.scss\"\n        },\n        \"logical_operators\": {\n            \"match\": \"\\\\b(not|or|and)\\\\b\",\n            \"name\": \"keyword.operator.logical.scss\"\n        },\n        \"map\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.map.begin.bracket.round.scss\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.map.end.bracket.round.scss\"\n                }\n            },\n            \"name\": \"meta.definition.variable.map.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment_block\"\n                },\n                {\n                    \"include\": \"#comment_line\"\n                },\n                {\n                    \"match\": \"\\\\b([\\\\w-]+)\\\\s*(:)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.type.map.key.scss\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.separator.key-value.scss\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.scss\"\n                },\n                {\n                    \"include\": \"#map\"\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"#variable\"\n                }\n            ]\n        },\n        \"operators\": {\n            \"match\": \"[-+*/](?!\\\\s*[-+*/])\",\n            \"name\": \"keyword.operator.css\"\n        },\n        \"parameters\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.begin.bracket.round.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.end.bracket.round.scss\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function_attributes\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#property_values\"\n                },\n                {\n                    \"include\": \"#comment_block\"\n                },\n                {\n                    \"match\": \"[^'\\\",) \\\\t]+\",\n                    \"name\": \"variable.parameter.url.scss\"\n                },\n                {\n                    \"match\": \",\",\n                    \"name\": \"punctuation.separator.delimiter.scss\"\n                }\n            ]\n        },\n        \"properties\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<![-a-z])(?=[-a-z])\",\n                    \"end\": \"$|(?![-a-z])\",\n                    \"name\": \"meta.property-name.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.css#property-names\"\n                        },\n                        {\n                            \"include\": \"#at_rule_include\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(:)\\\\s*(?!(\\\\s*{))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.key-value.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\s*(;|(?=}|\\\\)))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.terminator.rule.scss\"\n                        }\n                    },\n                    \"contentName\": \"meta.property-value.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#general\"\n                        },\n                        {\n                            \"include\": \"#property_values\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"property_list\": {\n            \"begin\": \"{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.property-list.begin.bracket.curly.scss\"\n                }\n            },\n            \"end\": \"}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.property-list.end.bracket.curly.scss\"\n                }\n            },\n            \"name\": \"meta.property-list.scss\",\n            \"patterns\": [\n                {\n                    \"include\": \"#flow_control\"\n                },\n                {\n                    \"include\": \"#rules\"\n                },\n                {\n                    \"include\": \"#properties\"\n                },\n                {\n                    \"include\": \"$self\"\n                }\n            ]\n        },\n        \"property_values\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string_single\"\n                },\n                {\n                    \"include\": \"#string_double\"\n                },\n                {\n                    \"include\": \"#constant_functions\"\n                },\n                {\n                    \"include\": \"#constant_sass_functions\"\n                },\n                {\n                    \"include\": \"#constant_important\"\n                },\n                {\n                    \"include\": \"#constant_default\"\n                },\n                {\n                    \"include\": \"#constant_optional\"\n                },\n                {\n                    \"include\": \"source.css#numeric-values\"\n                },\n                {\n                    \"include\": \"source.css#property-keywords\"\n                },\n                {\n                    \"include\": \"source.css#color-keywords\"\n                },\n                {\n                    \"include\": \"source.css#property-names\"\n                },\n                {\n                    \"include\": \"#constant_mathematical_symbols\"\n                },\n                {\n                    \"include\": \"#operators\"\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.begin.bracket.round.scss\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.end.bracket.round.scss\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#general\"\n                        },\n                        {\n                            \"include\": \"#property_values\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"rules\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#general\"\n                },\n                {\n                    \"include\": \"#at_rule_extend\"\n                },\n                {\n                    \"include\": \"#at_rule_content\"\n                },\n                {\n                    \"include\": \"#at_rule_include\"\n                },\n                {\n                    \"include\": \"#at_rule_media\"\n                },\n                {\n                    \"include\": \"#selectors\"\n                }\n            ]\n        },\n        \"selector_attribute\": {\n            \"match\":\n                \"(?xi)\\n(\\\\[)\\n\\\\s*\\n(\\n  (?:\\n    [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]       # Valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n    | \\\\#\\\\{                           # Interpolation (escaped to avoid Coffeelint errors)\\n    | \\\\$                              # Possible start of interpolation variable\\n    | }                                # Possible end of interpolation\\n  )+?\\n)\\n(?:\\n  \\\\s*([~|^$*]?=)\\\\s*\\n  (?:\\n    (\\n      (?:\\n        [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]       # Valid identifier characters\\n        | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n        | \\\\#\\\\{                           # Interpolation (escaped to avoid Coffeelint errors)\\n        | \\\\$                              # Possible start of interpolation variable\\n        | }                                # Possible end of interpolation\\n      )+\\n    )\\n    |\\n    ((\\\")(.*?)(\\\"))\\n    |\\n    ((')(.*?)('))\\n  )\\n)?\\n\\\\s*\\n(\\\\])\",\n            \"name\": \"meta.attribute-selector.scss\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.attribute-selector.begin.bracket.square.scss\"\n                },\n                \"2\": {\n                    \"name\": \"entity.other.attribute-name.attribute.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.scss\"\n                        }\n                    ]\n                },\n                \"3\": {\n                    \"name\": \"keyword.operator.scss\"\n                },\n                \"4\": {\n                    \"name\": \"string.unquoted.attribute-value.scss\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.scss\"\n                        }\n                    ]\n                },\n                \"5\": {\n                    \"name\": \"string.quoted.double.attribute-value.scss\"\n                },\n                \"6\": {\n                    \"name\": \"punctuation.definition.string.begin.scss\"\n                },\n                \"7\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.scss\"\n                        }\n                    ]\n                },\n                \"8\": {\n                    \"name\": \"punctuation.definition.string.end.scss\"\n                },\n                \"9\": {\n                    \"name\": \"string.quoted.single.attribute-value.scss\"\n                },\n                \"10\": {\n                    \"name\": \"punctuation.definition.string.begin.scss\"\n                },\n                \"11\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.scss\"\n                        }\n                    ]\n                },\n                \"12\": {\n                    \"name\": \"punctuation.definition.string.end.scss\"\n                },\n                \"13\": {\n                    \"name\": \"punctuation.definition.attribute-selector.end.bracket.square.scss\"\n                }\n            }\n        },\n        \"selector_class\": {\n            \"match\":\n                \"(?x)\\n(\\\\.)                                  # Valid class-name\\n(\\n  (?: [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]     # Valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n    | \\\\#\\\\{                           # Interpolation (escaped to avoid Coffeelint errors)\\n    | \\\\$                              # Possible start of interpolation variable\\n    | }                                # Possible end of interpolation\\n  )+\\n)                                      # Followed by either:\\n(?= $                                  # - End of the line\\n  | [\\\\s,.\\\\#)\\\\[:{>+~|]               # - Another selector\\n  | /\\\\*                               # - A block comment\\n)\",\n            \"name\": \"entity.other.attribute-name.class.css\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.scss\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"selector_custom\": {\n            \"match\":\n                \"\\\\b([a-zA-Z0-9]+(-[a-zA-Z0-9]+)+)(?=\\\\.|\\\\s++[^:]|\\\\s*[,\\\\[{]|:(link|visited|hover|active|focus|target|lang|disabled|enabled|checked|indeterminate|root|nth-(child|last-child|of-type|last-of-type)|first-child|last-child|first-of-type|last-of-type|only-child|only-of-type|empty|not|valid|invalid)(\\\\([0-9A-Za-z]*\\\\))?)\",\n            \"name\": \"entity.name.tag.custom.scss\"\n        },\n        \"selector_id\": {\n            \"match\":\n                \"(?x)\\n(\\\\#)                                  # Valid id-name\\n(\\n  (?: [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]     # Valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n    | \\\\#\\\\{                           # Interpolation (escaped to avoid Coffeelint errors)\\n    | \\\\$                              # Possible start of interpolation variable\\n    | }                                # Possible end of interpolation\\n  )+\\n)                                      # Followed by either:\\n(?= $                                  # - End of the line\\n  | [\\\\s,.\\\\#)\\\\[:{>+~|]               # - Another selector\\n  | /\\\\*                               # - A block comment\\n)\",\n            \"name\": \"entity.other.attribute-name.id.css\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.identifier.scss\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"selector_placeholder\": {\n            \"match\":\n                \"(?x)\\n(%)                                    # Valid placeholder-name\\n(\\n  (?: [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]     # Valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n    | \\\\#\\\\{                           # Interpolation (escaped to avoid Coffeelint errors)\\n    | \\\\$                              # Possible start of interpolation variable\\n    | }                                # Possible end of interpolation\\n  )+\\n)                                      # Followed by either:\\n(?= ;                                  # - End of statement\\n  | $                                  # - End of the line\\n  | [\\\\s,.\\\\#)\\\\[:{>+~|]               # - Another selector\\n  | /\\\\*                               # - A block comment\\n)\",\n            \"name\": \"entity.other.attribute-name.placeholder.css\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.identifier.scss\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"parent_selector_suffix\": {\n            \"match\":\n                \"(?x)\\n(?<=&)\\n(\\n  (?: [-a-zA-Z_0-9]|[^\\\\x00-\\\\x7F]     # Valid identifier characters\\n    | \\\\\\\\(?:[0-9a-fA-F]{1,6}|.)       # Escape sequence\\n    | \\\\#\\\\{                           # Interpolation (escaped to avoid Coffeelint errors)\\n    | \\\\$                              # Possible start of interpolation variable\\n    | }                                # Possible end of interpolation\\n  )+\\n)                                      # Followed by either:\\n(?= $                                  # - End of the line\\n  | [\\\\s,.\\\\#)\\\\[:{>+~|]               # - Another selector\\n  | /\\\\*                               # - A block comment\\n)\",\n            \"name\": \"entity.other.attribute-name.parent-selector-suffix.css\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.entity.css\"\n                },\n                \"2\": {\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\([0-9a-fA-F]{1,6}|.)\",\n                            \"name\": \"constant.character.escape.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\$|}\",\n                            \"name\": \"invalid.illegal.identifier.scss\"\n                        }\n                    ]\n                }\n            }\n        },\n        \"selector_pseudo_class\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"((:)\\\\bnth-(?:child|last-child|of-type|last-of-type))(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.attribute-name.pseudo-class.css\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.entity.css\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.pseudo-class.begin.bracket.round.css\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.pseudo-class.end.bracket.round.css\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#interpolation\"\n                        },\n                        {\n                            \"match\": \"\\\\d+\",\n                            \"name\": \"constant.numeric.css\"\n                        },\n                        {\n                            \"match\": \"(?<=\\\\d)n\\\\b|\\\\b(n|even|odd)\\\\b\",\n                            \"name\": \"constant.other.scss\"\n                        },\n                        {\n                            \"match\": \"\\\\w+\",\n                            \"name\": \"invalid.illegal.scss\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"source.css#pseudo-classes\"\n                },\n                {\n                    \"include\": \"source.css#pseudo-elements\"\n                },\n                {\n                    \"include\": \"source.css#functional-pseudo-classes\"\n                }\n            ]\n        },\n        \"selectors\": {\n            \"patterns\": [\n                {\n                    \"include\": \"source.css#tag-names\"\n                },\n                {\n                    \"include\": \"#selector_custom\"\n                },\n                {\n                    \"include\": \"#selector_class\"\n                },\n                {\n                    \"include\": \"#selector_id\"\n                },\n                {\n                    \"include\": \"#selector_pseudo_class\"\n                },\n                {\n                    \"include\": \"#tag_wildcard\"\n                },\n                {\n                    \"include\": \"#tag_parent_reference\"\n                },\n                {\n                    \"include\": \"source.css#pseudo-elements\"\n                },\n                {\n                    \"include\": \"#selector_attribute\"\n                },\n                {\n                    \"include\": \"#selector_placeholder\"\n                },\n                {\n                    \"include\": \"#parent_selector_suffix\"\n                }\n            ]\n        },\n        \"string_double\": {\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.scss\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.scss\"\n                }\n            },\n            \"name\": \"string.quoted.double.scss\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\(\\\\h{1,6}|.)\",\n                    \"name\": \"constant.character.escape.scss\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"string_single\": {\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.scss\"\n                }\n            },\n            \"end\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.scss\"\n                }\n            },\n            \"name\": \"string.quoted.single.scss\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\(\\\\h{1,6}|.)\",\n                    \"name\": \"constant.character.escape.scss\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"tag_parent_reference\": {\n            \"match\": \"&\",\n            \"name\": \"entity.name.tag.reference.scss\"\n        },\n        \"tag_wildcard\": {\n            \"match\": \"\\\\*\",\n            \"name\": \"entity.name.tag.wildcard.scss\"\n        },\n        \"variable\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#variables\"\n                },\n                {\n                    \"include\": \"#interpolation\"\n                }\n            ]\n        },\n        \"variable_setting\": {\n            \"begin\": \"(?=\\\\$[\\\\w-]+\\\\s*:)\",\n            \"end\": \";\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.terminator.rule.scss\"\n                }\n            },\n            \"contentName\": \"meta.definition.variable.scss\",\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\$[\\\\w-]+(?=\\\\s*:)\",\n                    \"name\": \"variable.scss\"\n                },\n                {\n                    \"begin\": \":\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.separator.key-value.scss\"\n                        }\n                    },\n                    \"end\": \"(?=;)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment_block\"\n                        },\n                        {\n                            \"include\": \"#comment_line\"\n                        },\n                        {\n                            \"include\": \"#map\"\n                        },\n                        {\n                            \"include\": \"#property_values\"\n                        },\n                        {\n                            \"include\": \"#variable\"\n                        },\n                        {\n                            \"match\": \",\",\n                            \"name\": \"punctuation.separator.delimiter.scss\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"variables\": {\n            \"match\": \"(\\\\$|\\\\-\\\\-)[A-Za-z0-9_-]+\\\\b\",\n            \"name\": \"variable.scss\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/shell/syntaxes/shell.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/atom/language-shellscript/blob/master/grammars/shell-unix-bash.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/atom/language-shellscript/commit/4c3711edbe8eac6f501976893976b1ac6a043d50\",\n    \"name\": \"Shell Script\",\n    \"scopeName\": \"source.shell\",\n    \"patterns\": [\n        {\n            \"include\": \"#comment\"\n        },\n        {\n            \"include\": \"#pipeline\"\n        },\n        {\n            \"include\": \"#list\"\n        },\n        {\n            \"include\": \"#compound-command\"\n        },\n        {\n            \"include\": \"#loop\"\n        },\n        {\n            \"include\": \"#string\"\n        },\n        {\n            \"include\": \"#function-definition\"\n        },\n        {\n            \"include\": \"#variable\"\n        },\n        {\n            \"include\": \"#interpolation\"\n        },\n        {\n            \"include\": \"#heredoc\"\n        },\n        {\n            \"include\": \"#herestring\"\n        },\n        {\n            \"include\": \"#redirection\"\n        },\n        {\n            \"include\": \"#pathname\"\n        },\n        {\n            \"include\": \"#keyword\"\n        },\n        {\n            \"include\": \"#support\"\n        }\n    ],\n    \"repository\": {\n        \"case-clause\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?=\\\\S)\",\n                    \"end\": \";;\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.terminator.case-clause.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.case-clause.shell\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"\\\\(|(?=\\\\S)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.case-pattern.shell\"\n                                }\n                            },\n                            \"end\": \"\\\\)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.case-pattern.shell\"\n                                }\n                            },\n                            \"name\": \"meta.scope.case-pattern.shell\",\n                            \"patterns\": [\n                                {\n                                    \"match\": \"\\\\|\",\n                                    \"name\": \"punctuation.separator.pipe-sign.shell\"\n                                },\n                                {\n                                    \"include\": \"#string\"\n                                },\n                                {\n                                    \"include\": \"#variable\"\n                                },\n                                {\n                                    \"include\": \"#interpolation\"\n                                },\n                                {\n                                    \"include\": \"#pathname\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\": \"(?<=\\\\))\",\n                            \"end\": \"(?=;;)\",\n                            \"name\": \"meta.scope.case-clause-body.shell\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"comment\": {\n            \"begin\": \"(^\\\\s+)?(?<=^|\\\\W)(?<!-)(?=#)(?!#{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.whitespace.comment.leading.shell\"\n                }\n            },\n            \"end\": \"(?!\\\\G)\",\n            \"patterns\": [\n                {\n                    \"begin\": \"#!\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.shebang.shell\"\n                        }\n                    },\n                    \"end\": \"$\",\n                    \"name\": \"comment.line.number-sign.shebang.shell\"\n                },\n                {\n                    \"begin\": \"#\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.shell\"\n                        }\n                    },\n                    \"end\": \"$\",\n                    \"name\": \"comment.line.number-sign.shell\"\n                }\n            ]\n        },\n        \"compound-command\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\[{1,2}\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.logical-expression.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\]{1,2}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.logical-expression.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.logical-expression.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#logical-expression\"\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\({2}\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\){2}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.other.math.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#math\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.subshell.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.subshell.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.subshell.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=\\\\s|^){(?=\\\\s|$)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;)\\\\s*(})\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.group.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"function-definition\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)(function)\\\\s+([^\\\\s\\\\\\\\]+)(?:\\\\s*(\\\\(\\\\)))?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.arguments.shell\"\n                        }\n                    },\n                    \"end\": \";|&|$\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.function.shell\"\n                        }\n                    },\n                    \"name\": \"meta.function.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)([^\\\\s\\\\\\\\=]+)\\\\s*(\\\\(\\\\))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.function.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.arguments.shell\"\n                        }\n                    },\n                    \"end\": \";|&|$\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.function.shell\"\n                        }\n                    },\n                    \"name\": \"meta.function.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"heredoc\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(RUBY)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(RUBY)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.ruby.shell\",\n                    \"contentName\": \"source.ruby.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.ruby\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(RUBY)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(RUBY)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.ruby.shell\",\n                    \"contentName\": \"source.ruby.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.ruby\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(PYTHON)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(PYTHON)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.python.shell\",\n                    \"contentName\": \"source.python.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.python\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(PYTHON)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(PYTHON)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.python.shell\",\n                    \"contentName\": \"source.python.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.python\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(APPLESCRIPT)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(APPLESCRIPT)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.applescript.shell\",\n                    \"contentName\": \"source.applescript.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.applescript\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(APPLESCRIPT)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(APPLESCRIPT)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.applescript.shell\",\n                    \"contentName\": \"source.applescript.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.applescript\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(HTML)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(HTML)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.html.shell\",\n                    \"contentName\": \"text.html.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.basic\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(HTML)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(HTML)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.html.shell\",\n                    \"contentName\": \"text.html.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.basic\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(MARKDOWN)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(MARKDOWN)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.markdown.shell\",\n                    \"contentName\": \"text.html.markdown.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.markdown\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(MARKDOWN)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(MARKDOWN)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.markdown.shell\",\n                    \"contentName\": \"text.html.markdown.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.markdown\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(TEXTILE)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(TEXTILE)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.textile.shell\",\n                    \"contentName\": \"text.html.textile.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.textile\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(TEXTILE)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(TEXTILE)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.textile.shell\",\n                    \"contentName\": \"text.html.textile.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.textile\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*(SHELL)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(\\\\3)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"contentName\": \"source.shell.embedded.shell\",\n                    \"name\": \"string.unquoted.heredoc.no-indent.shell.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.shell\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*(SHELL)(?=\\\\s|;|&|<|\\\"|')\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(\\\\3)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.shell.shell\",\n                    \"contentName\": \"source.shell.embedded.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.shell\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(<<)-\\\\s*(\\\"|'|)\\\\s*\\\\\\\\?([^;&<\\\\s]+)\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^\\\\t*(\\\\3)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.no-indent.shell\"\n                },\n                {\n                    \"begin\": \"(<<)\\\\s*(\\\"|'|)\\\\s*\\\\\\\\?([^;&<\\\\s]+)\\\\2\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.heredoc.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"end\": \"^(\\\\3)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.heredoc-token.shell\"\n                        }\n                    },\n                    \"name\": \"string.unquoted.heredoc.shell\"\n                }\n            ]\n        },\n        \"herestring\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(<<<)\\\\s*(('))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.herestring.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.quoted.single.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"(')\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"string.quoted.single.shell\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"meta.herestring.shell\",\n                    \"contentName\": \"string.quoted.single.shell\"\n                },\n                {\n                    \"begin\": \"(<<<)\\\\s*((\\\"))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.herestring.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.quoted.double.shell\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"(\\\")\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"string.quoted.double.shell\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"meta.herestring.shell\",\n                    \"contentName\": \"string.quoted.double.shell\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.herestring.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"string.unquoted.herestring.shell\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        }\n                    },\n                    \"match\": \"(<<<)\\\\s*(([^\\\\s)\\\\\\\\]|\\\\\\\\.)+)\",\n                    \"name\": \"meta.herestring.shell\"\n                }\n            ]\n        },\n        \"interpolation\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"\\\\$\\\\({2}\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\){2}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.other.math.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#math\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"`\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"`\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.interpolated.backtick.shell\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\[`\\\\\\\\$]\",\n                            \"name\": \"constant.character.escape.shell\"\n                        },\n                        {\n                            \"begin\": \"(?<=\\\\W)(?=#)(?!#{)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.whitespace.comment.leading.shell\"\n                                }\n                            },\n                            \"end\": \"(?!\\\\G)\",\n                            \"patterns\": [\n                                {\n                                    \"begin\": \"#\",\n                                    \"beginCaptures\": {\n                                        \"0\": {\n                                            \"name\": \"punctuation.definition.comment.shell\"\n                                        }\n                                    },\n                                    \"end\": \"(?=`)\",\n                                    \"name\": \"comment.line.number-sign.shell\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\$\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.interpolated.dollar.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"keyword\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<=^|;|&|\\\\s)(then|else|elif|fi|for|in|do|done|select|case|continue|esac|while|until|return)(?=\\\\s|;|&|$)\",\n                    \"name\": \"keyword.control.shell\"\n                },\n                {\n                    \"match\": \"(?<=^|;|&|\\\\s)(?:export|declare|typeset|local|readonly)(?=\\\\s|;|&|$)\",\n                    \"name\": \"storage.modifier.shell\"\n                }\n            ]\n        },\n        \"list\": {\n            \"patterns\": [\n                {\n                    \"match\": \";|&&|&|\\\\|\\\\|\",\n                    \"name\": \"keyword.operator.list.shell\"\n                }\n            ]\n        },\n        \"logical-expression\": {\n            \"patterns\": [\n                {\n                    \"comment\": \"do we want a special rule for ( expr )?\",\n                    \"match\": \"=[=~]?|!=?|<|>|&&|\\\\|\\\\|\",\n                    \"name\": \"keyword.operator.logical.shell\"\n                },\n                {\n                    \"match\": \"(?<!\\\\S)-(nt|ot|ef|eq|ne|l[te]|g[te]|[a-hknoprstuwxzOGLSN])\",\n                    \"name\": \"keyword.operator.logical.shell\"\n                }\n            ]\n        },\n        \"loop\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)(for)\\\\s+(?=\\\\({2})\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;|&|\\\\s)done(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.for-loop.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)(for)\\\\s+(.+?)\\\\s+(in)(?=\\\\s|;|&|$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.loop.shell\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#string\"\n                                }\n                            ]\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;|&|\\\\s)done(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.for-in-loop.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)(while|until)(?=\\\\s|;|&|$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;|&|\\\\s)done(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.while-loop.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)(select)\\\\s+((?:[^\\\\s\\\\\\\\]|\\\\\\\\.)+)(?=\\\\s|;|&|$)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.loop.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;|&|\\\\s)(done)(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.select-block.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)case(?=\\\\s|;|&|$)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;|&|\\\\s)esac(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.case-block.shell\",\n                    \"patterns\": [\n                        {\n                            \"begin\": \"(?<=^|;|&|\\\\s)in(?=\\\\s|;|&|$)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"keyword.control.shell\"\n                                }\n                            },\n                            \"end\": \"(?<=^|;|&|\\\\s)(?=esac(\\\\s|;|&|$))\",\n                            \"name\": \"meta.scope.case-body.shell\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#case-clause\"\n                                },\n                                {\n                                    \"include\": \"$self\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<=^|;|&|\\\\s)if(?=\\\\s|;|&|$)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"end\": \"(?<=^|;|&|\\\\s)fi(?=\\\\s|;|&|$)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.shell\"\n                        }\n                    },\n                    \"name\": \"meta.scope.if-block.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"math\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#variable\"\n                },\n                {\n                    \"match\":\n                        \"\\\\+{1,2}|-{1,2}|!|~|\\\\*{1,2}|/|%|<[<=]?|>[>=]?|==|!=|^|\\\\|{1,2}|&{1,2}|\\\\?|\\\\:|,|=|[*/%+\\\\-&^|]=|<<=|>>=\",\n                    \"name\": \"keyword.operator.arithmetic.shell\"\n                },\n                {\n                    \"match\": \"0[xX][0-9A-Fa-f]+\",\n                    \"name\": \"constant.numeric.hex.shell\"\n                },\n                {\n                    \"match\": \"0\\\\d+\",\n                    \"name\": \"constant.numeric.octal.shell\"\n                },\n                {\n                    \"match\": \"\\\\d{1,2}#[0-9a-zA-Z@_]+\",\n                    \"name\": \"constant.numeric.other.shell\"\n                },\n                {\n                    \"match\": \"\\\\d+\",\n                    \"name\": \"constant.numeric.integer.shell\"\n                }\n            ]\n        },\n        \"pathname\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?<=\\\\s|:|=|^)~\",\n                    \"name\": \"keyword.operator.tilde.shell\"\n                },\n                {\n                    \"match\": \"\\\\*|\\\\?\",\n                    \"name\": \"keyword.operator.glob.shell\"\n                },\n                {\n                    \"begin\": \"([?*+@!])(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.extglob.shell\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.extglob.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.extglob.shell\"\n                        }\n                    },\n                    \"name\": \"meta.structure.extglob.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"pipeline\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?<=^|;|&|\\\\s)(time)(?=\\\\s|;|&|$)\",\n                    \"name\": \"keyword.other.shell\"\n                },\n                {\n                    \"match\": \"[|!]\",\n                    \"name\": \"keyword.operator.pipe.shell\"\n                }\n            ]\n        },\n        \"redirection\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"[><]\\\\(\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.interpolated.process-substitution.shell\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"match\": \"(?<![<>])(&>|\\\\d*>&\\\\d*|\\\\d*(>>|>|<)|\\\\d*<&|\\\\d*<>)(?![<>])\",\n                    \"name\": \"keyword.operator.redirect.shell\"\n                }\n            ]\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"match\": \"\\\\\\\\.\",\n                    \"name\": \"constant.character.escape.shell\"\n                },\n                {\n                    \"begin\": \"'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.shell\"\n                },\n                {\n                    \"begin\": \"\\\\$?\\\"\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.quoted.double.shell\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\[\\\\$`\\\"\\\\\\\\\\\\n]\",\n                            \"name\": \"constant.character.escape.shell\"\n                        },\n                        {\n                            \"include\": \"#variable\"\n                        },\n                        {\n                            \"include\": \"#interpolation\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\$'\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.shell\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.shell\"\n                        }\n                    },\n                    \"name\": \"string.quoted.single.dollar.shell\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\\\\\(a|b|e|f|n|r|t|v|\\\\\\\\|')\",\n                            \"name\": \"constant.character.escape.ansi-c.shell\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\[0-9]{3}\",\n                            \"name\": \"constant.character.escape.octal.shell\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\x[0-9a-fA-F]{2}\",\n                            \"name\": \"constant.character.escape.hex.shell\"\n                        },\n                        {\n                            \"match\": \"\\\\\\\\c.\",\n                            \"name\": \"constant.character.escape.control-char.shell\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"support\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?<=^|;|&|\\\\s)(?::|\\\\.)(?=\\\\s|;|&|$)\",\n                    \"name\": \"support.function.builtin.shell\"\n                },\n                {\n                    \"match\":\n                        \"(?<=^|;|&|\\\\s)(?:alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|dirs|disown|echo|enable|eval|exec|exit|false|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|popd|printf|pushd|pwd|read|readonly|set|shift|shopt|source|suspend|test|times|trap|true|type|ulimit|umask|unalias|unset|wait)(?=\\\\s|;|&|$)\",\n                    \"name\": \"support.function.builtin.shell\"\n                }\n            ]\n        },\n        \"variable\": {\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.shell\"\n                        }\n                    },\n                    \"match\": \"(\\\\$)[a-zA-Z_][a-zA-Z0-9_]*\",\n                    \"name\": \"variable.other.normal.shell\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.shell\"\n                        }\n                    },\n                    \"match\": \"(\\\\$)[-*@#?$!0_]\",\n                    \"name\": \"variable.other.special.shell\"\n                },\n                {\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.variable.shell\"\n                        }\n                    },\n                    \"match\": \"(\\\\$)[1-9]\",\n                    \"name\": \"variable.other.positional.shell\"\n                },\n                {\n                    \"begin\": \"\\\\${\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.shell\"\n                        }\n                    },\n                    \"end\": \"}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.variable.shell\"\n                        }\n                    },\n                    \"name\": \"variable.other.bracket.shell\",\n                    \"patterns\": [\n                        {\n                            \"match\": \"!|:[-=?]?|\\\\*|@|#{1,2}|%{1,2}|/\",\n                            \"name\": \"keyword.operator.expansion.shell\"\n                        },\n                        {\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"punctuation.section.array.shell\"\n                                },\n                                \"3\": {\n                                    \"name\": \"punctuation.section.array.shell\"\n                                }\n                            },\n                            \"match\": \"(\\\\[)([^\\\\]]+)(\\\\])\"\n                        },\n                        {\n                            \"include\": \"#variable\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/swift/syntaxes/swift.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/freebroccolo/atom-language-swift/blob/master/grammars/swift.cson\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/freebroccolo/atom-language-swift/commit/fb7c93e0174dea69c8685c00deeb53d480d1d202\",\n    \"name\": \"Swift\",\n    \"scopeName\": \"source.swift\",\n    \"patterns\": [\n        {\n            \"name\": \"keyword.others.swift\",\n            \"match\":\n                \"^\\\\s*(#if|#else|#endif|#elseif|@warn_unused_result|@discardableResult|@IBAction|@IBOutlet|@IBDesignable|@IBInspectable)\\\\b\"\n        },\n        {\n            \"name\": \"keyword.declaration.swift\",\n            \"match\": \"\\\\b(deinit|import|init|subscript)\\\\b\"\n        },\n        {\n            \"name\": \"storage.type.swift\",\n            \"match\":\n                \"\\\\b(precedencegroup|class|struct|enum|extension|protocol|let|var|typealias)\\\\b\"\n        },\n        {\n            \"name\": \"storage.modifier.swift\",\n            \"match\":\n                \"\\\\b(final|internal|private|fileprivate|public|open|static|required|convenience)\\\\b\"\n        },\n        {\n            \"name\": \"keyword.statement.swift\",\n            \"match\":\n                \"\\\\b(try|catch|repeat|break|case|continue|default|do|else|fallthrough|if|in|for|return|switch|where|while|guard|defer)\\\\b\"\n        },\n        {\n            \"name\": \"support.type.swift\",\n            \"match\":\n                \"(?x) \\\\b(Character|U?Int|U?Int(8|16|32|64) |Float|Double|Float(32|64)|Bool|String|Date|Data|URL |(double|float)[234]|(double|float)[234]x[234] |Any |AnyObject |Error |Equatable |Hashable |Comparable |CustomDebugStringConvertible |CustomStringConvertible |OptionSet |ManagedBuffer |ManagedBufferPointer |BitwiseOperations |CountedSet |Counter |Directions |ExpressibleByArrayLiteral |ExpressibleByBooleanLiteral |ExpressibleByDictionaryLiteral |ExpressibleByExtendedGraphemeClusterLiteral |ExpressibleByFloatLitera |ExpressibleByIntegerLiteral |ExpressibleByNilLiteral |ExpressibleByStringInterpolation |ExpressibleByStringLiteral |ExpressibleByUnicodeScalarLiteral |OrderedSet |PaperSize |RawRepresentable |(UI|NS|CF|CG)[A-Z][a-zA-Z0-9]+ |Stream |(In|Out)putStream |FileManager |Array |Unsafe[a-zA-Z]*Pointer |Bundle |Jex)\\\\b\"\n        },\n        {\n            \"name\": \"support.function.swift\",\n            \"match\": \"\\\\b(assert|assertionFailure|print)\\\\b\"\n        },\n        {\n            \"name\": \"keyword.expressions-and-types.swift\",\n            \"match\":\n                \"\\\\b(as|dynamicType|is|new|super|self|Self|Type|#column|#file|#function|#line)\\\\b\"\n        },\n        {\n            \"name\": \"keyword.reserved.swift\",\n            \"match\":\n                \"\\\\b(associativity|didSet|get|infix|inout|left|mutating|nonmutating|operator|override|postfix|precedence|prefix|right|set|unowned|unowned(safe)|unowned(unsafe)|weak|willSet)\\\\b\"\n        },\n        {\n            \"name\": \"constant.language.swift\",\n            \"match\": \"\\\\b(true|false|nil|none)\\\\b\"\n        },\n        {\n            \"name\": \"entity.name.function.swift\",\n            \"match\": \"\\\\bfunc\\\\s+([^\\\\t\\\\n\\\\x20\\\\x28]+)\"\n        },\n        {\n            \"include\": \"#comment\"\n        },\n        {\n            \"include\": \"#literal\"\n        },\n        {\n            \"include\": \"#operator\"\n        }\n    ],\n    \"repository\": {\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.block.swift\",\n                    \"begin\": \"/\\\\*\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.begin.swift\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.end.swift\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?(?=//)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.swift\"\n                        }\n                    },\n                    \"end\": \"(?!\\\\G)\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"comment.line.double-slash.swift\",\n                            \"begin\": \"//\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.comment.swift\"\n                                }\n                            },\n                            \"end\": \"\\\\n\",\n                            \"patterns\": [\n                                {\n                                    \"name\": \"punctuation.separator.continuation.swift\",\n                                    \"match\": \"(?>\\\\\\\\\\\\s*\\\\n)\"\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        \"escaped-char\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.escape.swift\",\n                    \"match\": \"\\\\\\\\[0\\\\\\\\tnr\\\"']\"\n                },\n                {\n                    \"name\": \"constant.character.escape.swift\",\n                    \"match\": \"\\\\\\\\(x\\\\h{2}|u\\\\h{4}|U\\\\h{8})\"\n                },\n                {\n                    \"name\": \"invalid.illegal.constant.character.escape.swift\",\n                    \"match\": \"\\\\\\\\[^uxU]\"\n                }\n            ]\n        },\n        \"identifier\": {\n            \"match\":\n                \"(?x) (?<identifier>                \\\\g<identifier-head> \\\\g<identifier-characters>? |                         ` \\\\g<identifier-head> \\\\g<identifier-characters>? ` ){0} (?<identifier-head>           [ a-z A-Z ] |                           [ \\\\u00A8 \\\\u00AA \\\\u00AD \\\\u00AF \\\\u00B2-\\\\u00B5 \\\\u00B7-\\\\u00BA ] |                           [ \\\\u00BC-\\\\u00BE \\\\u00C0-\\\\u00D6 \\\\u00D8-\\\\u00F6 \\\\u00F8-\\\\u00FF ] |                           [ \\\\u0100-\\\\u02FF \\\\u0370-\\\\u167F \\\\u1681-\\\\u180D \\\\u180F-\\\\u1DBF ] |                           [ \\\\u1E00-\\\\u1FFF ] |                           [ \\\\u200B-\\\\u200D \\\\u202A-\\\\u202E \\\\u203F-\\\\u2040 \\\\u2054 \\\\u2060-\\\\u206F ] |                           [ \\\\u2070-\\\\u20CF \\\\u2100-\\\\u218F \\\\u2460-\\\\u24FF \\\\u2776-\\\\u2793 ] |                           [ \\\\u2C00-\\\\u2DFF \\\\u2E80-\\\\u2FFF ] |                           [ \\\\u3004-\\\\u3007 \\\\u3021-\\\\u302F \\\\u3031-\\\\u303F \\\\u3040-\\\\uD7FF ] |                           [ \\\\uF900-\\\\uFD3D \\\\uFD40-\\\\uFDCF \\\\uFDF0-\\\\uFE1F \\\\uFE30-\\\\uFE44 ] |                           [ \\\\uFE47-\\\\uFFFD ] |                           [ \\\\u10000-\\\\u1FFFD \\\\u20000-\\\\u2FFFD \\\\u30000-\\\\u3FFFD \\\\u40000-\\\\u4FFFD ] |                           [ \\\\u50000-\\\\u5FFFD \\\\u60000-\\\\u6FFFD \\\\u70000-\\\\u7FFFD \\\\u80000-\\\\u8FFFD ] |                           [ \\\\u90000-\\\\u9FFFD \\\\uA0000-\\\\uAFFFD \\\\uB0000-\\\\uBFFFD \\\\uC0000-\\\\uCFFFD ] |                           [ \\\\uD0000-\\\\uDFFFD \\\\uE0000-\\\\uEFFFD ] ){0} (?<identifier-character>      \\\\d |                           [ \\\\u0300-\\\\u036F \\\\u1DC0-\\\\u1DFF \\\\u20D0-\\\\u20FF \\\\uFE20-\\\\uFE2F ] |                           \\\\g<identifier-head> ){0} (?<identifier-characters>     \\\\g<identifier-character> \\\\g<identifier-characters>? ){0} (?<implicit-parameter-name>   (?<!\\\\g<identifier-head>) \\\\$ \\\\d+ (?!\\\\g<identifier-head>) (?# FIXME) ){0} \\\\g<identifier> | \\\\g<implicit-parameter-name>\",\n            \"captures\": {\n                \"5\": {\n                    \"name\": \"variable.other.positional.swift\"\n                }\n            }\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#literal-number\"\n                },\n                {\n                    \"include\": \"#literal-string\"\n                }\n            ]\n        },\n        \"literal-number\": {\n            \"name\": \"constant.numeric.swift\",\n            \"match\":\n                \"(?x) (?### INTEGER ###) (?<integer-literal>                 \\\\g<binary-literal> |                                 \\\\g<octal-literal> |                                 \\\\g<hexadecimal-literal> |                                 \\\\g<decimal-literal> ){0} (?### BINARY ###) (?<binary-literal>                  \\\\b 0b \\\\g<binary-digit> \\\\g<binary-literal-characters>? \\\\b ){0} (?<binary-digit>                    [0-1] ){0} (?<binary-literal-character>        \\\\g<binary-digit> |                                 _ ){0} (?<binary-literal-characters>       \\\\g<binary-literal-character> \\\\g<binary-literal-characters>? ){0} (?### OCTAL ###) (?<octal-literal>                   \\\\b 0o \\\\g<octal-digit> \\\\g<octal-literal-characters>? \\\\b ){0} (?<octal-digit>                     [0-7] ){0} (?<octal-literal-character>         \\\\g<octal-digit> |                                 _ ){0} (?<octal-literal-characters>        \\\\g<octal-literal-character> \\\\g<octal-literal-characters>? ){0} (?### DECIMAL ###) (?<decimal-literal>                 \\\\b \\\\g<decimal-digit> \\\\g<decimal-literal-characters>? \\\\b ){0} (?<decimal-digit>                   \\\\d ){0} (?<decimal-literal-character>       \\\\g<decimal-digit> |                                 _ ){0} (?<decimal-literal-characters>      \\\\g<decimal-literal-character> \\\\g<decimal-literal-characters>? ){0} (?### HEXADECIMAL ###) (?<hexadecimal-literal>             \\\\b 0x \\\\g<hexadecimal-digit> \\\\g<hexadecimal-literal-characters>? \\\\b ){0} (?<hexadecimal-digit>               \\\\h ){0} (?<hexadecimal-literal-character>   \\\\g<hexadecimal-digit> |                                 _ ){0} (?<hexadecimal-literal-characters>  \\\\g<hexadecimal-literal-character> \\\\g<hexadecimal-literal-characters>? ){0} (?### FLOATING POINT ###) (?<floating-point-literal>          \\\\b \\\\g<decimal-literal>     \\\\g<decimal-fraction>?     \\\\g<decimal-exponent>? \\\\b |                                 \\\\b \\\\g<hexadecimal-literal> \\\\g<hexadecimal-fraction>? \\\\g<hexadecimal-exponent> \\\\b ){0} (?<decimal-fraction>                \\\\. \\\\g<decimal-literal> ){0} (?<decimal-exponent>                \\\\g<floating-point-e> \\\\g<sign>? \\\\g<decimal-literal> ){0} (?<hexadecimal-fraction>            \\\\. \\\\g<hexadecimal-literal>? ){0} (?<hexadecimal-exponent>            \\\\g<floating-point-p> \\\\g<sign>? \\\\g<hexadecimal-literal> ){0} (?<floating-point-e>                [eE] ){0} (?<floating-point-p>                [pP] ){0} (?<sign>                            [+-] ){0} (?!0[box]) \\\\g<floating-point-literal> |            \\\\g<integer-literal>\"\n        },\n        \"literal-string\": {\n            \"name\": \"string.quoted.double.swift\",\n            \"begin\": \"\\\"\",\n            \"end\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.swift\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.swift\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#quoted-text\"\n                }\n            ]\n        },\n        \"operator\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#operator-character\"\n                }\n            ]\n        },\n        \"operator-character\": {\n            \"name\": \"keyword.operator.swift\",\n            \"match\": \"[\\\\/=\\\\-+!*%<>&|^~,\\\\?:\\\\[\\\\]]\"\n        },\n        \"quoted-text\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.embedded.line.swift\",\n                    \"contentName\": \"source.swift\",\n                    \"begin\": \"\\\\\\\\\\\\(\",\n                    \"end\": \"\\\\)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.begin.swift\"\n                        }\n                    },\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.section.embedded.end.swift\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"$self\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#escaped-char\"\n                }\n            ]\n        },\n        \"whitespace\": {\n            \"match\":\n                \"(?x) [ \\\\u0020 (?#           space) \\\\u000A (?#       line-feed) \\\\u000D (?# carriage-return) \\\\u0009 (?#  horizontal-tab) \\\\u000B (?#    vertical-tab) \\\\u000C (?#       form-feed) \\\\u0000 (?#            null) ]\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/theme-dracula/colors/dracula.json",
    "content": "{\n    \"name\": \"dracula\",\n    \"baseVimTheme\": \"dracula\",\n    \"colors\": {\n        \"background\": \"#191A21\",\n        \"foreground\": \"#f8f8f2\",\n\n        \"title.background\": \"#21222d\",\n        \"title.foreground\": \"#f8f8f2\",\n\n        \"editor.background\": \"#21222d\",\n        \"editor.foreground\": \"#f8f8f2\",\n\n        \"tabs.background\": \"#282a36\",\n        \"tabs.foreground\": \"#f8f8f2\",\n\n        \"toolTip.background\": \"#21222d\",\n        \"toolTip.foreground\": \"#f8f8f2\",\n        \"toolTip.border\": \"#000000\",\n\n        \"menu.background\": \"#21222d\",\n        \"menu.foreground\": \"#f8f8f2\",\n        \"menu.border\": \"#000000\",\n\n        \"contextMenu.background\": \"#21222d\",\n        \"contextMenu.foreground\": \"#f8f8f2\",\n        \"contextMenu.border\": \"#000000\",\n        \"contextMenu.highlight\": \"#44475a\",\n\n        \"sidebar.background\": \"#21222d\",\n        \"sidebar.foreground\": \"#f8f8f2\",\n        \"sidebar.active.background\": \"#21222d\",\n        \"sidebar.selection.border\": \"#000000\",\n\n        \"statusBar.background\": \"#21222d\",\n        \"statusBar.foreground\": \"#f8f8f2\",\n\n        \"fileExplorer.background\": \"#21222d\",\n        \"fileExplorer.foreground\": \"#f8f8f2\",\n\n        \"highlight.mode.insert.background\": \"#8be9fd\",\n        \"highlight.mode.insert.foreground\": \"#000000\",\n\n        \"highlight.mode.normal.background\": \"#50fa7b\",\n        \"highlight.mode.normal.foreground\": \"#000000\",\n\n        \"highlight.mode.operator.background\": \"#ff79c6\",\n        \"highlight.mode.operator.foreground\": \"#000000\",\n\n        \"highlight.mode.visual.background\": \"#ffb86c\",\n        \"highlight.mode.visual.foreground\": \"#000000\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-dracula/colors/dracula.vim",
    "content": "\" Dracula Theme: v1.5.0 {{{\n\"\n\" https://github.com/zenorocha/dracula-theme\n\"\n\" Copyright 2016, All rights reserved\n\"\n\" Code licensed under the MIT license\n\" http://zenorocha.mit-license.org\n\"\n\" @author Trevor Heins <@heinst>\n\" @author Éverton Ribeiro <nuxlli@gmail.com>\n\" @author Derek Sifford <dereksifford@gmail.com>\n\" @author Zeno Rocha <hi@zenorocha.com>\nscriptencoding utf8\n\" }}}\n\n\" Configuration: {{{\n\nif v:version > 580\n  highlight clear\n  if exists('syntax_on')\n    syntax reset\n  endif\nendif\n\nlet g:colors_name = 'dracula'\n\nif !(has('termguicolors') && &termguicolors) && !has('gui_running') && &t_Co != 256\n  finish\nendif\n\n\" Palette: {{{2\n\nlet s:fg        = ['#F8F8F2', 255]\n\nlet s:bglighter = ['#424450', 238]\nlet s:bglight   = ['#343746', 237]\nlet s:bg        = ['#282A36', 236]\nlet s:bgdark    = ['#21222C', 235]\nlet s:bgdarker  = ['#191A21', 234]\n\nlet s:subtle    = ['#424450', 238]\n\nlet s:selection = ['#44475A', 239]\nlet s:comment   = ['#6272A4',  61]\nlet s:cyan      = ['#8BE9FD', 117]\nlet s:green     = ['#50FA7B',  84]\nlet s:orange    = ['#FFB86C', 215]\nlet s:pink      = ['#FF79C6', 212]\nlet s:purple    = ['#BD93F9', 141]\nlet s:red       = ['#FF5555', 203]\nlet s:yellow    = ['#F1FA8C', 228]\n\nlet s:none      = ['NONE', 'NONE']\n\nlet g:dracula_palette = {\n      \\ 'fg': s:fg,\n      \\ 'bg': s:bg,\n      \\ 'selection': s:selection,\n      \\ 'comment': s:comment,\n      \\ 'cyan': s:cyan,\n      \\ 'green': s:green,\n      \\ 'orange': s:orange,\n      \\ 'pink': s:pink,\n      \\ 'purple': s:purple,\n      \\ 'red': s:red,\n      \\ 'yellow': s:yellow,\n      \\\n      \\ 'bglighter': s:bglighter,\n      \\ 'bglight': s:bglight,\n      \\ 'bgdark': s:bgdark,\n      \\ 'bgdarker': s:bgdarker,\n      \\ 'subtle': s:subtle,\n      \\}\n\nif has('nvim')\n  let g:terminal_color_0  = '#21222C'\n  let g:terminal_color_1  = '#FF5555'\n  let g:terminal_color_2  = '#50FA7B'\n  let g:terminal_color_3  = '#F1FA8C'\n  let g:terminal_color_4  = '#BD93F9'\n  let g:terminal_color_5  = '#FF79C6'\n  let g:terminal_color_6  = '#8BE9FD'\n  let g:terminal_color_7  = '#F8F8F2'\n  let g:terminal_color_8  = '#6272A4'\n  let g:terminal_color_9  = '#FF6E6E'\n  let g:terminal_color_10 = '#69FF94'\n  let g:terminal_color_11 = '#FFFFA5'\n  let g:terminal_color_12 = '#D6ACFF'\n  let g:terminal_color_13 = '#FF92DF'\n  let g:terminal_color_14 = '#A4FFFF'\n  let g:terminal_color_15 = '#FFFFFF'\nendif\n\n\" }}}2\n\" User Configuration: {{{2\n\nif !exists('g:dracula_bold')\n  let g:dracula_bold = 1\nendif\n\nif !exists('g:dracula_italic')\n  let g:dracula_italic = 1\nendif\n\nif !exists('g:dracula_underline')\n  let g:dracula_underline = 1\nendif\n\nif !exists('g:dracula_undercurl') && g:dracula_underline != 0\n  let g:dracula_undercurl = 1\nendif\n\nif !exists('g:dracula_inverse')\n  let g:dracula_inverse = 1\nendif\n\nif !exists('g:dracula_colorterm')\n  let g:dracula_colorterm = 1\nendif\n\n\"}}}2\n\" Script Helpers: {{{2\n\nlet s:attrs = {\n      \\ 'bold': g:dracula_bold == 1 ? 'bold' : 0,\n      \\ 'italic': g:dracula_italic == 1 ? 'italic' : 0,\n      \\ 'underline': g:dracula_underline == 1 ? 'underline' : 0,\n      \\ 'undercurl': g:dracula_undercurl == 1 ? 'undercurl' : 0,\n      \\ 'inverse': g:dracula_inverse == 1 ? 'inverse' : 0,\n      \\}\n\nfunction! s:h(scope, fg, ...) \" bg, attr_list, special\n  let l:fg = copy(a:fg)\n  let l:bg = get(a:, 1, ['NONE', 'NONE'])\n\n  let l:attr_list = filter(get(a:, 2, ['NONE']), 'type(v:val) == 1')\n  let l:attrs = len(l:attr_list) > 0 ? join(l:attr_list, ',') : 'NONE'\n\n  \" Falls back to coloring foreground group on terminals because\n  \" nearly all do not support undercurl\n  let l:special = get(a:, 3, ['NONE', 'NONE'])\n  if l:special[0] !=# 'NONE' && l:fg[0] ==# 'NONE' && !has('gui_running')\n    let l:fg[0] = l:special[0]\n    let l:fg[1] = l:special[1]\n  endif\n\n  let l:hl_string = [\n        \\ 'highlight', a:scope,\n        \\ 'guifg=' . l:fg[0], 'ctermfg=' . l:fg[1],\n        \\ 'guibg=' . l:bg[0], 'ctermbg=' . l:bg[1],\n        \\ 'gui=' . l:attrs, 'cterm=' . l:attrs,\n        \\ 'guisp=' . l:special[0],\n        \\]\n\n  execute join(l:hl_string, ' ')\nendfunction\n\nfunction! s:Background()\n  if g:dracula_colorterm || has('gui_running')\n    return s:bg\n  else\n    return s:none\n  endif\nendfunction\n\n\"}}}2\n\" Dracula Highlight Groups: {{{2\n\ncall s:h('DraculaBgLight', s:none, s:bglight)\ncall s:h('DraculaBgLighter', s:none, s:bglighter)\ncall s:h('DraculaBgDark', s:none, s:bgdark)\ncall s:h('DraculaBgDarker', s:none, s:bgdarker)\n\ncall s:h('DraculaFg', s:fg)\ncall s:h('DraculaFgUnderline', s:fg, s:none, [s:attrs.underline])\ncall s:h('DraculaFgBold', s:fg, s:none, [s:attrs.bold])\n\ncall s:h('DraculaComment', s:comment)\ncall s:h('DraculaCommentBold', s:comment, s:none, [s:attrs.bold])\n\ncall s:h('DraculaSelection', s:none, s:selection)\n\ncall s:h('DraculaSubtle', s:subtle)\n\ncall s:h('DraculaCyan', s:cyan)\ncall s:h('DraculaCyanItalic', s:cyan, s:none, [s:attrs.italic])\n\ncall s:h('DraculaGreen', s:green)\ncall s:h('DraculaGreenBold', s:green, s:none, [s:attrs.bold])\ncall s:h('DraculaGreenItalic', s:green, s:none, [s:attrs.italic])\ncall s:h('DraculaGreenItalicUnderline', s:green, s:none, [s:attrs.italic, s:attrs.underline])\n\ncall s:h('DraculaOrange', s:orange)\ncall s:h('DraculaOrangeBold', s:orange, s:none, [s:attrs.bold])\ncall s:h('DraculaOrangeItalic', s:orange, s:none, [s:attrs.italic])\ncall s:h('DraculaOrangeBoldItalic', s:orange, s:none, [s:attrs.bold, s:attrs.italic])\ncall s:h('DraculaOrangeInverse', s:bg, s:orange)\n\ncall s:h('DraculaPink', s:pink)\ncall s:h('DraculaPinkItalic', s:pink, s:none, [s:attrs.italic])\n\ncall s:h('DraculaPurple', s:purple)\ncall s:h('DraculaPurpleBold', s:purple, s:none, [s:attrs.bold])\ncall s:h('DraculaPurpleItalic', s:purple, s:none, [s:attrs.italic])\n\ncall s:h('DraculaRed', s:red)\ncall s:h('DraculaRedInverse', s:fg, s:red)\n\ncall s:h('DraculaYellow', s:yellow)\ncall s:h('DraculaYellowItalic', s:yellow, s:none, [s:attrs.italic])\n\ncall s:h('DraculaError', s:red, s:none, [], s:red)\n\ncall s:h('DraculaErrorLine', s:none, s:none, [s:attrs.undercurl], s:red)\ncall s:h('DraculaWarnLine', s:none, s:none, [s:attrs.undercurl], s:orange)\ncall s:h('DraculaInfoLine', s:none, s:none, [s:attrs.undercurl], s:cyan)\n\ncall s:h('DraculaTodo', s:cyan, s:none, [s:attrs.bold, s:attrs.inverse])\ncall s:h('DraculaSearch', s:green, s:none, [s:attrs.inverse])\ncall s:h('DraculaBoundary', s:comment, s:bgdark)\ncall s:h('DraculaLink', s:cyan, s:none, [s:attrs.underline])\n\ncall s:h('DraculaDiffChange', s:none, s:none)\ncall s:h('DraculaDiffText', s:bg, s:orange)\ncall s:h('DraculaDiffDelete', s:red, s:bgdark)\n\n\" }}}2\n\n\" }}}\n\" User Interface: {{{\n\nset background=dark\n\n\" Required as some plugins will overwrite\ncall s:h('Normal', s:fg, s:Background())\ncall s:h('StatusLine', s:none, s:bglighter, [s:attrs.bold])\ncall s:h('StatusLineNC', s:none, s:bglight)\ncall s:h('WildMenu', s:bg, s:purple, [s:attrs.bold])\ncall s:h('CursorLine', s:none, s:subtle)\n\nhi! link ColorColumn  DraculaSelection\nhi! link CursorColumn DraculaSelection\nhi! link CursorLineNr DraculaYellow\nhi! link DiffAdd      DraculaGreen\nhi! link DiffAdded    DiffAdd\nhi! link DiffChange   DraculaDiffChange\nhi! link DiffDelete   DraculaDiffDelete\nhi! link DiffRemoved  DiffDelete\nhi! link DiffText     DraculaDiffText\nhi! link Directory    DraculaPurpleBold\nhi! link ErrorMsg     DraculaRedInverse\nhi! link FoldColumn   DraculaSubtle\nhi! link Folded       DraculaBoundary\nhi! link IncSearch    DraculaOrangeInverse\nhi! link LineNr       DraculaComment\nhi! link MoreMsg      DraculaFgBold\nhi! link NonText      DraculaSubtle\nhi! link Pmenu        DraculaBgDark\nhi! link PmenuSbar    DraculaBgDark\nhi! link PmenuSel     DraculaSelection\nhi! link PmenuThumb   DraculaSelection\nhi! link Question     DraculaFgBold\nhi! link Search       DraculaSearch\nhi! link SignColumn   DraculaComment\nhi! link TabLine      DraculaBoundary\nhi! link TabLineFill  DraculaBgDarker\nhi! link TabLineSel   Normal\nhi! link Title        DraculaGreenBold\nhi! link VertSplit    DraculaBoundary\nhi! link Visual       DraculaSelection\nhi! link VisualNOS    Visual\nhi! link WarningMsg   DraculaOrangeInverse\n\n\" }}}\n\" Syntax: {{{\n\n\" Required as some plugins will overwrite\ncall s:h('MatchParen', s:fg, s:pink, [s:attrs.underline])\ncall s:h('Conceal', s:comment, s:bglight)\n\nhi! link Comment DraculaComment\nhi! link Underlined DraculaFgUnderline\nhi! link Todo DraculaTodo\n\nhi! link Error DraculaError\nhi! link SpellBad DraculaErrorLine\nhi! link SpellLocal DraculaWarnLine\nhi! link SpellCap DraculaInfoLine\nhi! link SpellRare DraculaInfoLine\n\nhi! link Constant DraculaPurple\nhi! link String DraculaYellow\nhi! link Character DraculaPink\nhi! link Number Constant\nhi! link Boolean Constant\nhi! link Float Constant\n\nhi! link Identifier DraculaFg\nhi! link Function DraculaGreen\n\nhi! link Statement DraculaPink\nhi! link Conditional DraculaPink\nhi! link Repeat DraculaPink\nhi! link Label DraculaPink\nhi! link Operator DraculaPink\nhi! link Keyword DraculaPink\nhi! link Exception DraculaPink\n\nhi! link PreProc DraculaPink\nhi! link Include DraculaPink\nhi! link Define DraculaPink\nhi! link Macro DraculaPink\nhi! link PreCondit DraculaPink\nhi! link StorageClass DraculaPink\nhi! link Structure DraculaPink\nhi! link Typedef DraculaPink\n\nhi! link Type DraculaCyanItalic\n\nhi! link Delimiter DraculaFg\n\nhi! link Special DraculaPink\nhi! link SpecialKey DraculaRed\nhi! link SpecialComment DraculaCyanItalic\nhi! link Tag DraculaCyan\nhi! link helpHyperTextJump DraculaLink\nhi! link helpCommand DraculaPurple\nhi! link helpExample DraculaGreen\nhi! link helpBacktick Special\n\n\"}}}\n\n\" vim: fdm=marker ts=2 sts=2 sw=2:\n"
  },
  {
    "path": "extensions/theme-dracula/package.json",
    "content": "{\n    \"name\": \"theme-dracula\",\n    \"version\": \"0.0.1\",\n    \"description\": \"Onivim Dracula Theme\",\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"engines\": {\n        \"oni\": \"0.3.6\"\n    },\n    \"contributes\": {\n        \"themes\": [{\n            \"name\": \"dracula\",\n            \"path\": \"colors/dracula.json\"\n        }]\n    }, \n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/theme-gruvbox/colors/gruvbox.vim",
    "content": "\" -----------------------------------------------------------------------------\n\" File: gruvbox.vim\n\" Description: Retro groove color scheme for Vim\n\" Author: morhetz <morhetz@gmail.com>\n\" Source: https://github.com/morhetz/gruvbox\n\" Last Modified: 12 Aug 2017\n\" -----------------------------------------------------------------------------\n\n\" Supporting code -------------------------------------------------------------\n\" Initialisation: {{{\n\nif version > 580\n  hi clear\n  if exists(\"syntax_on\")\n    syntax reset\n  endif\nendif\n\nlet g:colors_name='gruvbox'\n\nif !(has('termguicolors') && &termguicolors) && !has('gui_running') && &t_Co != 256\n  finish\nendif\n\n\" }}}\n\" Global Settings: {{{\n\nif !exists('g:gruvbox_bold')\n  let g:gruvbox_bold=1\nendif\nif !exists('g:gruvbox_italic')\n  if has('gui_running') || $TERM_ITALICS == 'true'\n    let g:gruvbox_italic=1\n  else\n    let g:gruvbox_italic=0\n  endif\nendif\nif !exists('g:gruvbox_undercurl')\n  let g:gruvbox_undercurl=1\nendif\nif !exists('g:gruvbox_underline')\n  let g:gruvbox_underline=1\nendif\nif !exists('g:gruvbox_inverse')\n  let g:gruvbox_inverse=1\nendif\n\nif !exists('g:gruvbox_guisp_fallback') || index(['fg', 'bg'], g:gruvbox_guisp_fallback) == -1\n  let g:gruvbox_guisp_fallback='NONE'\nendif\n\nif !exists('g:gruvbox_improved_strings')\n  let g:gruvbox_improved_strings=0\nendif\n\nif !exists('g:gruvbox_improved_warnings')\n  let g:gruvbox_improved_warnings=0\nendif\n\nif !exists('g:gruvbox_termcolors')\n  let g:gruvbox_termcolors=256\nendif\n\nif !exists('g:gruvbox_invert_indent_guides')\n  let g:gruvbox_invert_indent_guides=0\nendif\n\nif exists('g:gruvbox_contrast')\n  echo 'g:gruvbox_contrast is deprecated; use g:gruvbox_contrast_light and g:gruvbox_contrast_dark instead'\nendif\n\nif !exists('g:gruvbox_contrast_dark')\n  let g:gruvbox_contrast_dark='medium'\nendif\n\nif !exists('g:gruvbox_contrast_light')\n  let g:gruvbox_contrast_light='medium'\nendif\n\nlet s:is_dark=(&background == 'dark')\n\n\" }}}\n\" Palette: {{{\n\n\" setup palette dictionary\nlet s:gb = {}\n\n\" fill it with absolute colors\nlet s:gb.dark0_hard  = ['#1d2021', 234]     \" 29-32-33\nlet s:gb.dark0       = ['#282828', 235]     \" 40-40-40\nlet s:gb.dark0_soft  = ['#32302f', 236]     \" 50-48-47\nlet s:gb.dark1       = ['#3c3836', 237]     \" 60-56-54\nlet s:gb.dark2       = ['#504945', 239]     \" 80-73-69\nlet s:gb.dark3       = ['#665c54', 241]     \" 102-92-84\nlet s:gb.dark4       = ['#7c6f64', 243]     \" 124-111-100\nlet s:gb.dark4_256   = ['#7c6f64', 243]     \" 124-111-100\n\nlet s:gb.gray_245    = ['#928374', 245]     \" 146-131-116\nlet s:gb.gray_244    = ['#928374', 244]     \" 146-131-116\n\nlet s:gb.light0_hard = ['#f9f5d7', 230]     \" 249-245-215\nlet s:gb.light0      = ['#fbf1c7', 229]     \" 253-244-193\nlet s:gb.light0_soft = ['#f2e5bc', 228]     \" 242-229-188\nlet s:gb.light1      = ['#ebdbb2', 223]     \" 235-219-178\nlet s:gb.light2      = ['#d5c4a1', 250]     \" 213-196-161\nlet s:gb.light3      = ['#bdae93', 248]     \" 189-174-147\nlet s:gb.light4      = ['#a89984', 246]     \" 168-153-132\nlet s:gb.light4_256  = ['#a89984', 246]     \" 168-153-132\n\nlet s:gb.bright_red     = ['#fb4934', 167]     \" 251-73-52\nlet s:gb.bright_green   = ['#b8bb26', 142]     \" 184-187-38\nlet s:gb.bright_yellow  = ['#fabd2f', 214]     \" 250-189-47\nlet s:gb.bright_blue    = ['#83a598', 109]     \" 131-165-152\nlet s:gb.bright_purple  = ['#d3869b', 175]     \" 211-134-155\nlet s:gb.bright_aqua    = ['#8ec07c', 108]     \" 142-192-124\nlet s:gb.bright_orange  = ['#fe8019', 208]     \" 254-128-25\n\nlet s:gb.neutral_red    = ['#cc241d', 124]     \" 204-36-29\nlet s:gb.neutral_green  = ['#98971a', 106]     \" 152-151-26\nlet s:gb.neutral_yellow = ['#d79921', 172]     \" 215-153-33\nlet s:gb.neutral_blue   = ['#458588', 66]      \" 69-133-136\nlet s:gb.neutral_purple = ['#b16286', 132]     \" 177-98-134\nlet s:gb.neutral_aqua   = ['#689d6a', 72]      \" 104-157-106\nlet s:gb.neutral_orange = ['#d65d0e', 166]     \" 214-93-14\n\nlet s:gb.faded_red      = ['#9d0006', 88]      \" 157-0-6\nlet s:gb.faded_green    = ['#79740e', 100]     \" 121-116-14\nlet s:gb.faded_yellow   = ['#b57614', 136]     \" 181-118-20\nlet s:gb.faded_blue     = ['#076678', 24]      \" 7-102-120\nlet s:gb.faded_purple   = ['#8f3f71', 96]      \" 143-63-113\nlet s:gb.faded_aqua     = ['#427b58', 66]      \" 66-123-88\nlet s:gb.faded_orange   = ['#af3a03', 130]     \" 175-58-3\n\n\" }}}\n\" Setup Emphasis: {{{\n\nlet s:bold = 'bold,'\nif g:gruvbox_bold == 0\n  let s:bold = ''\nendif\n\nlet s:italic = 'italic,'\nif g:gruvbox_italic == 0\n  let s:italic = ''\nendif\n\nlet s:underline = 'underline,'\nif g:gruvbox_underline == 0\n  let s:underline = ''\nendif\n\nlet s:undercurl = 'undercurl,'\nif g:gruvbox_undercurl == 0\n  let s:undercurl = ''\nendif\n\nlet s:inverse = 'inverse,'\nif g:gruvbox_inverse == 0\n  let s:inverse = ''\nendif\n\n\" }}}\n\" Setup Colors: {{{\n\nlet s:vim_bg = ['bg', 'bg']\nlet s:vim_fg = ['fg', 'fg']\nlet s:none = ['NONE', 'NONE']\n\n\" determine relative colors\nif s:is_dark\n  let s:bg0  = s:gb.dark0\n  if g:gruvbox_contrast_dark == 'soft'\n    let s:bg0  = s:gb.dark0_soft\n  elseif g:gruvbox_contrast_dark == 'hard'\n    let s:bg0  = s:gb.dark0_hard\n  endif\n\n  let s:bg1  = s:gb.dark1\n  let s:bg2  = s:gb.dark2\n  let s:bg3  = s:gb.dark3\n  let s:bg4  = s:gb.dark4\n\n  let s:gray = s:gb.gray_245\n\n  let s:fg0 = s:gb.light0\n  let s:fg1 = s:gb.light1\n  let s:fg2 = s:gb.light2\n  let s:fg3 = s:gb.light3\n  let s:fg4 = s:gb.light4\n\n  let s:fg4_256 = s:gb.light4_256\n\n  let s:red    = s:gb.bright_red\n  let s:green  = s:gb.bright_green\n  let s:yellow = s:gb.bright_yellow\n  let s:blue   = s:gb.bright_blue\n  let s:purple = s:gb.bright_purple\n  let s:aqua   = s:gb.bright_aqua\n  let s:orange = s:gb.bright_orange\nelse\n  let s:bg0  = s:gb.light0\n  if g:gruvbox_contrast_light == 'soft'\n    let s:bg0  = s:gb.light0_soft\n  elseif g:gruvbox_contrast_light == 'hard'\n    let s:bg0  = s:gb.light0_hard\n  endif\n\n  let s:bg1  = s:gb.light1\n  let s:bg2  = s:gb.light2\n  let s:bg3  = s:gb.light3\n  let s:bg4  = s:gb.light4\n\n  let s:gray = s:gb.gray_244\n\n  let s:fg0 = s:gb.dark0\n  let s:fg1 = s:gb.dark1\n  let s:fg2 = s:gb.dark2\n  let s:fg3 = s:gb.dark3\n  let s:fg4 = s:gb.dark4\n\n  let s:fg4_256 = s:gb.dark4_256\n\n  let s:red    = s:gb.faded_red\n  let s:green  = s:gb.faded_green\n  let s:yellow = s:gb.faded_yellow\n  let s:blue   = s:gb.faded_blue\n  let s:purple = s:gb.faded_purple\n  let s:aqua   = s:gb.faded_aqua\n  let s:orange = s:gb.faded_orange\nendif\n\n\" reset to 16 colors fallback\nif g:gruvbox_termcolors == 16\n  let s:bg0[1]    = 0\n  let s:fg4[1]    = 7\n  let s:gray[1]   = 8\n  let s:red[1]    = 9\n  let s:green[1]  = 10\n  let s:yellow[1] = 11\n  let s:blue[1]   = 12\n  let s:purple[1] = 13\n  let s:aqua[1]   = 14\n  let s:fg1[1]    = 15\nendif\n\n\" save current relative colors back to palette dictionary\nlet s:gb.bg0 = s:bg0\nlet s:gb.bg1 = s:bg1\nlet s:gb.bg2 = s:bg2\nlet s:gb.bg3 = s:bg3\nlet s:gb.bg4 = s:bg4\n\nlet s:gb.gray = s:gray\n\nlet s:gb.fg0 = s:fg0\nlet s:gb.fg1 = s:fg1\nlet s:gb.fg2 = s:fg2\nlet s:gb.fg3 = s:fg3\nlet s:gb.fg4 = s:fg4\n\nlet s:gb.fg4_256 = s:fg4_256\n\nlet s:gb.red    = s:red\nlet s:gb.green  = s:green\nlet s:gb.yellow = s:yellow\nlet s:gb.blue   = s:blue\nlet s:gb.purple = s:purple\nlet s:gb.aqua   = s:aqua\nlet s:gb.orange = s:orange\n\n\" }}}\n\" Setup Terminal Colors For Neovim: {{{\n\nif has('nvim')\n  let g:terminal_color_0 = s:bg0[0]\n  let g:terminal_color_8 = s:gray[0]\n\n  let g:terminal_color_1 = s:gb.neutral_red[0]\n  let g:terminal_color_9 = s:red[0]\n\n  let g:terminal_color_2 = s:gb.neutral_green[0]\n  let g:terminal_color_10 = s:green[0]\n\n  let g:terminal_color_3 = s:gb.neutral_yellow[0]\n  let g:terminal_color_11 = s:yellow[0]\n\n  let g:terminal_color_4 = s:gb.neutral_blue[0]\n  let g:terminal_color_12 = s:blue[0]\n\n  let g:terminal_color_5 = s:gb.neutral_purple[0]\n  let g:terminal_color_13 = s:purple[0]\n\n  let g:terminal_color_6 = s:gb.neutral_aqua[0]\n  let g:terminal_color_14 = s:aqua[0]\n\n  let g:terminal_color_7 = s:fg4[0]\n  let g:terminal_color_15 = s:fg1[0]\nendif\n\n\" }}}\n\" Overload Setting: {{{\n\nlet s:hls_cursor = s:orange\nif exists('g:gruvbox_hls_cursor')\n  let s:hls_cursor = get(s:gb, g:gruvbox_hls_cursor)\nendif\n\nlet s:number_column = s:none\nif exists('g:gruvbox_number_column')\n  let s:number_column = get(s:gb, g:gruvbox_number_column)\nendif\n\nlet s:sign_column = s:bg1\n\nif exists('g:gitgutter_override_sign_column_highlight') &&\n      \\ g:gitgutter_override_sign_column_highlight == 1\n  let s:sign_column = s:number_column\nelse\n  let g:gitgutter_override_sign_column_highlight = 0\n\n  if exists('g:gruvbox_sign_column')\n    let s:sign_column = get(s:gb, g:gruvbox_sign_column)\n  endif\nendif\n\nlet s:color_column = s:bg1\nif exists('g:gruvbox_color_column')\n  let s:color_column = get(s:gb, g:gruvbox_color_column)\nendif\n\nlet s:vert_split = s:bg0\nif exists('g:gruvbox_vert_split')\n  let s:vert_split = get(s:gb, g:gruvbox_vert_split)\nendif\n\nlet s:invert_signs = ''\nif exists('g:gruvbox_invert_signs')\n  if g:gruvbox_invert_signs == 1\n    let s:invert_signs = s:inverse\n  endif\nendif\n\nlet s:invert_selection = s:inverse\nif exists('g:gruvbox_invert_selection')\n  if g:gruvbox_invert_selection == 0\n    let s:invert_selection = ''\n  endif\nendif\n\nlet s:invert_tabline = ''\nif exists('g:gruvbox_invert_tabline')\n  if g:gruvbox_invert_tabline == 1\n    let s:invert_tabline = s:inverse\n  endif\nendif\n\nlet s:italicize_comments = s:italic\nif exists('g:gruvbox_italicize_comments')\n  if g:gruvbox_italicize_comments == 0\n    let s:italicize_comments = ''\n  endif\nendif\n\nlet s:italicize_strings = ''\nif exists('g:gruvbox_italicize_strings')\n  if g:gruvbox_italicize_strings == 1\n    let s:italicize_strings = s:italic\n  endif\nendif\n\n\" }}}\n\" Highlighting Function: {{{\n\nfunction! s:HL(group, fg, ...)\n  \" Arguments: group, guifg, guibg, gui, guisp\n\n  \" foreground\n  let fg = a:fg\n\n  \" background\n  if a:0 >= 1\n    let bg = a:1\n  else\n    let bg = s:none\n  endif\n\n  \" emphasis\n  if a:0 >= 2 && strlen(a:2)\n    let emstr = a:2\n  else\n    let emstr = 'NONE,'\n  endif\n\n  \" special fallback\n  if a:0 >= 3\n    if g:gruvbox_guisp_fallback != 'NONE'\n      let fg = a:3\n    endif\n\n    \" bg fallback mode should invert higlighting\n    if g:gruvbox_guisp_fallback == 'bg'\n      let emstr .= 'inverse,'\n    endif\n  endif\n\n  let histring = [ 'hi', a:group,\n        \\ 'guifg=' . fg[0], 'ctermfg=' . fg[1],\n        \\ 'guibg=' . bg[0], 'ctermbg=' . bg[1],\n        \\ 'gui=' . emstr[:-2], 'cterm=' . emstr[:-2]\n        \\ ]\n\n  \" special\n  if a:0 >= 3\n    call add(histring, 'guisp=' . a:3[0])\n  endif\n\n  execute join(histring, ' ')\nendfunction\n\n\" }}}\n\" Gruvbox Hi Groups: {{{\n\n\" memoize common hi groups\ncall s:HL('GruvboxFg0', s:fg0)\ncall s:HL('GruvboxFg1', s:fg1)\ncall s:HL('GruvboxFg2', s:fg2)\ncall s:HL('GruvboxFg3', s:fg3)\ncall s:HL('GruvboxFg4', s:fg4)\ncall s:HL('GruvboxGray', s:gray)\ncall s:HL('GruvboxBg0', s:bg0)\ncall s:HL('GruvboxBg1', s:bg1)\ncall s:HL('GruvboxBg2', s:bg2)\ncall s:HL('GruvboxBg3', s:bg3)\ncall s:HL('GruvboxBg4', s:bg4)\n\ncall s:HL('GruvboxRed', s:red)\ncall s:HL('GruvboxRedBold', s:red, s:none, s:bold)\ncall s:HL('GruvboxGreen', s:green)\ncall s:HL('GruvboxGreenBold', s:green, s:none, s:bold)\ncall s:HL('GruvboxYellow', s:yellow)\ncall s:HL('GruvboxYellowBold', s:yellow, s:none, s:bold)\ncall s:HL('GruvboxBlue', s:blue)\ncall s:HL('GruvboxBlueBold', s:blue, s:none, s:bold)\ncall s:HL('GruvboxPurple', s:purple)\ncall s:HL('GruvboxPurpleBold', s:purple, s:none, s:bold)\ncall s:HL('GruvboxAqua', s:aqua)\ncall s:HL('GruvboxAquaBold', s:aqua, s:none, s:bold)\ncall s:HL('GruvboxOrange', s:orange)\ncall s:HL('GruvboxOrangeBold', s:orange, s:none, s:bold)\n\ncall s:HL('GruvboxRedSign', s:red, s:sign_column, s:invert_signs)\ncall s:HL('GruvboxGreenSign', s:green, s:sign_column, s:invert_signs)\ncall s:HL('GruvboxYellowSign', s:yellow, s:sign_column, s:invert_signs)\ncall s:HL('GruvboxBlueSign', s:blue, s:sign_column, s:invert_signs)\ncall s:HL('GruvboxPurpleSign', s:purple, s:sign_column, s:invert_signs)\ncall s:HL('GruvboxAquaSign', s:aqua, s:sign_column, s:invert_signs)\n\n\" }}}\n\n\" Vanilla colorscheme ---------------------------------------------------------\n\" General UI: {{{\n\n\" Normal text\ncall s:HL('Normal', s:fg1, s:bg0)\n\n\" Correct background (see issue #7):\n\" --- Problem with changing between dark and light on 256 color terminal\n\" --- https://github.com/morhetz/gruvbox/issues/7\nif s:is_dark\n  set background=dark\nelse\n  set background=light\nendif\n\nif version >= 700\n  \" Screen line that the cursor is\n  call s:HL('CursorLine',   s:none, s:bg1)\n  \" Screen column that the cursor is\n  hi! link CursorColumn CursorLine\n\n  \" Tab pages line filler\n  call s:HL('TabLineFill', s:bg4, s:bg1, s:invert_tabline)\n  \" Active tab page label\n  call s:HL('TabLineSel', s:green, s:bg1, s:invert_tabline)\n  \" Not active tab page label\n  hi! link TabLine TabLineFill\n\n  \" Match paired bracket under the cursor\n  call s:HL('MatchParen', s:none, s:bg3, s:bold)\nendif\n\nif version >= 703\n  \" Highlighted screen columns\n  call s:HL('ColorColumn',  s:none, s:color_column)\n\n  \" Concealed element: \\lambda → λ\n  call s:HL('Conceal', s:blue, s:none)\n\n  \" Line number of CursorLine\n  call s:HL('CursorLineNr', s:yellow, s:bg1)\nendif\n\nhi! link NonText GruvboxBg2\nhi! link SpecialKey GruvboxBg2\n\ncall s:HL('Visual',    s:none,  s:bg3, s:invert_selection)\nhi! link VisualNOS Visual\n\ncall s:HL('Search',    s:yellow, s:bg0, s:inverse)\ncall s:HL('IncSearch', s:hls_cursor, s:bg0, s:inverse)\n\ncall s:HL('Underlined', s:blue, s:none, s:underline)\n\ncall s:HL('StatusLine',   s:bg2, s:fg1, s:inverse)\ncall s:HL('StatusLineNC', s:bg1, s:fg4, s:inverse)\n\n\" The column separating vertically split windows\ncall s:HL('VertSplit', s:bg3, s:vert_split)\n\n\" Current match in wildmenu completion\ncall s:HL('WildMenu', s:blue, s:bg2, s:bold)\n\n\" Directory names, special names in listing\nhi! link Directory GruvboxGreenBold\n\n\" Titles for output from :set all, :autocmd, etc.\nhi! link Title GruvboxGreenBold\n\n\" Error messages on the command line\ncall s:HL('ErrorMsg',   s:bg0, s:red, s:bold)\n\" More prompt: -- More --\nhi! link MoreMsg GruvboxYellowBold\n\" Current mode message: -- INSERT --\nhi! link ModeMsg GruvboxYellowBold\n\" 'Press enter' prompt and yes/no questions\nhi! link Question GruvboxOrangeBold\n\" Warning messages\nhi! link WarningMsg GruvboxRedBold\n\n\" }}}\n\" Gutter: {{{\n\n\" Line number for :number and :# commands\ncall s:HL('LineNr', s:bg4, s:number_column)\n\n\" Column where signs are displayed\ncall s:HL('SignColumn', s:none, s:sign_column)\n\n\" Line used for closed folds\ncall s:HL('Folded', s:gray, s:bg1, s:italic)\n\" Column where folds are displayed\ncall s:HL('FoldColumn', s:gray, s:bg1)\n\n\" }}}\n\" Cursor: {{{\n\n\" Character under cursor\ncall s:HL('Cursor', s:none, s:none, s:inverse)\n\" Visual mode cursor, selection\nhi! link vCursor Cursor\n\" Input moder cursor\nhi! link iCursor Cursor\n\" Language mapping cursor\nhi! link lCursor Cursor\n\n\" }}}\n\" Syntax Highlighting: {{{\n\nif g:gruvbox_improved_strings == 0\n  hi! link Special GruvboxOrange\nelse\n  call s:HL('Special', s:orange, s:bg1, s:italicize_strings)\nendif\n\ncall s:HL('Comment', s:gray, s:none, s:italicize_comments)\ncall s:HL('Todo', s:vim_fg, s:vim_bg, s:bold . s:italic)\ncall s:HL('Error', s:red, s:vim_bg, s:bold . s:inverse)\n\n\" Generic statement\nhi! link Statement GruvboxRed\n\" if, then, else, endif, swicth, etc.\nhi! link Conditional GruvboxRed\n\" for, do, while, etc.\nhi! link Repeat GruvboxRed\n\" case, default, etc.\nhi! link Label GruvboxRed\n\" try, catch, throw\nhi! link Exception GruvboxRed\n\" sizeof, \"+\", \"*\", etc.\nhi! link Operator Normal\n\" Any other keyword\nhi! link Keyword GruvboxRed\n\n\" Variable name\nhi! link Identifier GruvboxBlue\n\" Function name\nhi! link Function GruvboxGreenBold\n\n\" Generic preprocessor\nhi! link PreProc GruvboxAqua\n\" Preprocessor #include\nhi! link Include GruvboxAqua\n\" Preprocessor #define\nhi! link Define GruvboxAqua\n\" Same as Define\nhi! link Macro GruvboxAqua\n\" Preprocessor #if, #else, #endif, etc.\nhi! link PreCondit GruvboxAqua\n\n\" Generic constant\nhi! link Constant GruvboxPurple\n\" Character constant: 'c', '/n'\nhi! link Character GruvboxPurple\n\" String constant: \"this is a string\"\nif g:gruvbox_improved_strings == 0\n  call s:HL('String',  s:green, s:none, s:italicize_strings)\nelse\n  call s:HL('String',  s:fg1, s:bg1, s:italicize_strings)\nendif\n\" Boolean constant: TRUE, false\nhi! link Boolean GruvboxPurple\n\" Number constant: 234, 0xff\nhi! link Number GruvboxPurple\n\" Floating point constant: 2.3e10\nhi! link Float GruvboxPurple\n\n\" Generic type\nhi! link Type GruvboxYellow\n\" static, register, volatile, etc\nhi! link StorageClass GruvboxOrange\n\" struct, union, enum, etc.\nhi! link Structure GruvboxAqua\n\" typedef\nhi! link Typedef GruvboxYellow\n\n\" }}}\n\" Completion Menu: {{{\n\nif version >= 700\n  \" Popup menu: normal item\n  call s:HL('Pmenu', s:fg1, s:bg2)\n  \" Popup menu: selected item\n  call s:HL('PmenuSel', s:bg2, s:blue, s:bold)\n  \" Popup menu: scrollbar\n  call s:HL('PmenuSbar', s:none, s:bg2)\n  \" Popup menu: scrollbar thumb\n  call s:HL('PmenuThumb', s:none, s:bg4)\nendif\n\n\" }}}\n\" Diffs: {{{\n\ncall s:HL('DiffDelete', s:red, s:bg0, s:inverse)\ncall s:HL('DiffAdd',    s:green, s:bg0, s:inverse)\n\"call s:HL('DiffChange', s:bg0, s:blue)\n\"call s:HL('DiffText',   s:bg0, s:yellow)\n\n\" Alternative setting\ncall s:HL('DiffChange', s:aqua, s:bg0, s:inverse)\ncall s:HL('DiffText',   s:yellow, s:bg0, s:inverse)\n\n\" }}}\n\" Spelling: {{{\n\nif has(\"spell\")\n  \" Not capitalised word, or compile warnings\n  if g:gruvbox_improved_warnings == 0\n    call s:HL('SpellCap',   s:none, s:none, s:undercurl, s:red)\n  else\n    call s:HL('SpellCap',   s:green, s:none, s:bold . s:italic)\n  endif\n  \" Not recognized word\n  call s:HL('SpellBad',   s:none, s:none, s:undercurl, s:blue)\n  \" Wrong spelling for selected region\n  call s:HL('SpellLocal', s:none, s:none, s:undercurl, s:aqua)\n  \" Rare word\n  call s:HL('SpellRare',  s:none, s:none, s:undercurl, s:purple)\nendif\n\n\" }}}\n\n\" Plugin specific -------------------------------------------------------------\n\" EasyMotion: {{{\n\nhi! link EasyMotionTarget Search\nhi! link EasyMotionShade Comment\n\n\" }}}\n\" Sneak: {{{\n\nhi! link Sneak Search\nhi! link SneakLabel Search\n\n\" }}}\n\" Indent Guides: {{{\n\nif !exists('g:indent_guides_auto_colors')\n  let g:indent_guides_auto_colors = 0\nendif\n\nif g:indent_guides_auto_colors == 0\n  if g:gruvbox_invert_indent_guides == 0\n    call s:HL('IndentGuidesOdd', s:vim_bg, s:bg2)\n    call s:HL('IndentGuidesEven', s:vim_bg, s:bg1)\n  else\n    call s:HL('IndentGuidesOdd', s:vim_bg, s:bg2, s:inverse)\n    call s:HL('IndentGuidesEven', s:vim_bg, s:bg3, s:inverse)\n  endif\nendif\n\n\" }}}\n\" IndentLine: {{{\n\nif !exists('g:indentLine_color_term')\n  let g:indentLine_color_term = s:bg2[1]\nendif\nif !exists('g:indentLine_color_gui')\n  let g:indentLine_color_gui = s:bg2[0]\nendif\n\n\" }}}\n\" Rainbow Parentheses: {{{\n\nif !exists('g:rbpt_colorpairs')\n  let g:rbpt_colorpairs =\n    \\ [\n      \\ ['blue', '#458588'], ['magenta', '#b16286'],\n      \\ ['red',  '#cc241d'], ['166',     '#d65d0e']\n    \\ ]\nendif\n\nlet g:rainbow_guifgs = [ '#d65d0e', '#cc241d', '#b16286', '#458588' ]\nlet g:rainbow_ctermfgs = [ '166', 'red', 'magenta', 'blue' ]\n\nif !exists('g:rainbow_conf')\n   let g:rainbow_conf = {}\nendif\nif !has_key(g:rainbow_conf, 'guifgs')\n   let g:rainbow_conf['guifgs'] = g:rainbow_guifgs\nendif\nif !has_key(g:rainbow_conf, 'ctermfgs')\n   let g:rainbow_conf['ctermfgs'] = g:rainbow_ctermfgs\nendif\n\nlet g:niji_dark_colours = g:rbpt_colorpairs\nlet g:niji_light_colours = g:rbpt_colorpairs\n\n\"}}}\n\" GitGutter: {{{\n\nhi! link GitGutterAdd GruvboxGreenSign\nhi! link GitGutterChange GruvboxAquaSign\nhi! link GitGutterDelete GruvboxRedSign\nhi! link GitGutterChangeDelete GruvboxAquaSign\n\n\" }}}\n\" GitCommit: \"{{{\n\nhi! link gitcommitSelectedFile GruvboxGreen\nhi! link gitcommitDiscardedFile GruvboxRed\n\n\" }}}\n\" Signify: {{{\n\nhi! link SignifySignAdd GruvboxGreenSign\nhi! link SignifySignChange GruvboxAquaSign\nhi! link SignifySignDelete GruvboxRedSign\n\n\" }}}\n\" Syntastic: {{{\n\ncall s:HL('SyntasticError', s:none, s:none, s:undercurl, s:red)\ncall s:HL('SyntasticWarning', s:none, s:none, s:undercurl, s:yellow)\n\nhi! link SyntasticErrorSign GruvboxRedSign\nhi! link SyntasticWarningSign GruvboxYellowSign\n\n\" }}}\n\" Signature: {{{\nhi! link SignatureMarkText   GruvboxBlueSign\nhi! link SignatureMarkerText GruvboxPurpleSign\n\n\" }}}\n\" ShowMarks: {{{\n\nhi! link ShowMarksHLl GruvboxBlueSign\nhi! link ShowMarksHLu GruvboxBlueSign\nhi! link ShowMarksHLo GruvboxBlueSign\nhi! link ShowMarksHLm GruvboxBlueSign\n\n\" }}}\n\" CtrlP: {{{\n\nhi! link CtrlPMatch GruvboxYellow\nhi! link CtrlPNoEntries GruvboxRed\nhi! link CtrlPPrtBase GruvboxBg2\nhi! link CtrlPPrtCursor GruvboxBlue\nhi! link CtrlPLinePre GruvboxBg2\n\ncall s:HL('CtrlPMode1', s:blue, s:bg2, s:bold)\ncall s:HL('CtrlPMode2', s:bg0, s:blue, s:bold)\ncall s:HL('CtrlPStats', s:fg4, s:bg2, s:bold)\n\n\" }}}\n\" Startify: {{{\n\nhi! link StartifyBracket GruvboxFg3\nhi! link StartifyFile GruvboxFg1\nhi! link StartifyNumber GruvboxBlue\nhi! link StartifyPath GruvboxGray\nhi! link StartifySlash GruvboxGray\nhi! link StartifySection GruvboxYellow\nhi! link StartifySpecial GruvboxBg2\nhi! link StartifyHeader GruvboxOrange\nhi! link StartifyFooter GruvboxBg2\n\n\" }}}\n\" Vimshell: {{{\n\nlet g:vimshell_escape_colors = [\n  \\ s:bg4[0], s:red[0], s:green[0], s:yellow[0],\n  \\ s:blue[0], s:purple[0], s:aqua[0], s:fg4[0],\n  \\ s:bg0[0], s:red[0], s:green[0], s:orange[0],\n  \\ s:blue[0], s:purple[0], s:aqua[0], s:fg0[0]\n  \\ ]\n\n\" }}}\n\" BufTabLine: {{{\n\ncall s:HL('BufTabLineCurrent', s:bg0, s:fg4)\ncall s:HL('BufTabLineActive', s:fg4, s:bg2)\ncall s:HL('BufTabLineHidden', s:bg4, s:bg1)\ncall s:HL('BufTabLineFill', s:bg0, s:bg0)\n\n\" }}}\n\" Asynchronous Lint Engine: {{{\n\ncall s:HL('ALEError', s:none, s:none, s:undercurl, s:red)\ncall s:HL('ALEWarning', s:none, s:none, s:undercurl, s:yellow)\ncall s:HL('ALEInfo', s:none, s:none, s:undercurl, s:blue)\n\nhi! link ALEErrorSign GruvboxRedSign\nhi! link ALEWarningSign GruvboxYellowSign\nhi! link ALEInfoSign GruvboxBlueSign\n\n\" }}}\n\" Dirvish: {{{\n\nhi! link DirvishPathTail GruvboxAqua\nhi! link DirvishArg GruvboxYellow\n\n\" }}}\n\" Netrw: {{{\n\nhi! link netrwDir GruvboxAqua\nhi! link netrwClassify GruvboxAqua\nhi! link netrwLink GruvboxGray\nhi! link netrwSymLink GruvboxFg1\nhi! link netrwExe GruvboxYellow\nhi! link netrwComment GruvboxGray\nhi! link netrwList GruvboxBlue\nhi! link netrwHelpCmd GruvboxAqua\nhi! link netrwCmdSep GruvboxFg3\nhi! link netrwVersion GruvboxGreen\n\n\" }}}\n\" NERDTree: {{{\n\nhi! link NERDTreeDir GruvboxAqua\nhi! link NERDTreeDirSlash GruvboxAqua\n\nhi! link NERDTreeOpenable GruvboxOrange\nhi! link NERDTreeClosable GruvboxOrange\n\nhi! link NERDTreeFile GruvboxFg1\nhi! link NERDTreeExecFile GruvboxYellow\n\nhi! link NERDTreeUp GruvboxGray\nhi! link NERDTreeCWD GruvboxGreen\nhi! link NERDTreeHelp GruvboxFg1\n\nhi! link NERDTreeToggleOn GruvboxGreen\nhi! link NERDTreeToggleOff GruvboxRed\n\n\" }}}\n\" Vim Multiple Cursors: {{{\n\ncall s:HL('multiple_cursors_cursor', s:none, s:none, s:inverse)\ncall s:HL('multiple_cursors_visual', s:none, s:bg2)\n\n\" }}}\n\n\" Filetype specific -----------------------------------------------------------\n\" Diff: {{{\n\nhi! link diffAdded GruvboxGreen\nhi! link diffRemoved GruvboxRed\nhi! link diffChanged GruvboxAqua\n\nhi! link diffFile GruvboxOrange\nhi! link diffNewFile GruvboxYellow\n\nhi! link diffLine GruvboxBlue\n\n\" }}}\n\" Html: {{{\n\nhi! link htmlTag GruvboxBlue\nhi! link htmlEndTag GruvboxBlue\n\nhi! link htmlTagName GruvboxAquaBold\nhi! link htmlArg GruvboxAqua\n\nhi! link htmlScriptTag GruvboxPurple\nhi! link htmlTagN GruvboxFg1\nhi! link htmlSpecialTagName GruvboxAquaBold\n\ncall s:HL('htmlLink', s:fg4, s:none, s:underline)\n\nhi! link htmlSpecialChar GruvboxOrange\n\ncall s:HL('htmlBold', s:vim_fg, s:vim_bg, s:bold)\ncall s:HL('htmlBoldUnderline', s:vim_fg, s:vim_bg, s:bold . s:underline)\ncall s:HL('htmlBoldItalic', s:vim_fg, s:vim_bg, s:bold . s:italic)\ncall s:HL('htmlBoldUnderlineItalic', s:vim_fg, s:vim_bg, s:bold . s:underline . s:italic)\n\ncall s:HL('htmlUnderline', s:vim_fg, s:vim_bg, s:underline)\ncall s:HL('htmlUnderlineItalic', s:vim_fg, s:vim_bg, s:underline . s:italic)\ncall s:HL('htmlItalic', s:vim_fg, s:vim_bg, s:italic)\n\n\" }}}\n\" Xml: {{{\n\nhi! link xmlTag GruvboxBlue\nhi! link xmlEndTag GruvboxBlue\nhi! link xmlTagName GruvboxBlue\nhi! link xmlEqual GruvboxBlue\nhi! link docbkKeyword GruvboxAquaBold\n\nhi! link xmlDocTypeDecl GruvboxGray\nhi! link xmlDocTypeKeyword GruvboxPurple\nhi! link xmlCdataStart GruvboxGray\nhi! link xmlCdataCdata GruvboxPurple\nhi! link dtdFunction GruvboxGray\nhi! link dtdTagName GruvboxPurple\n\nhi! link xmlAttrib GruvboxAqua\nhi! link xmlProcessingDelim GruvboxGray\nhi! link dtdParamEntityPunct GruvboxGray\nhi! link dtdParamEntityDPunct GruvboxGray\nhi! link xmlAttribPunct GruvboxGray\n\nhi! link xmlEntity GruvboxOrange\nhi! link xmlEntityPunct GruvboxOrange\n\" }}}\n\" Vim: {{{\n\ncall s:HL('vimCommentTitle', s:fg4_256, s:none, s:bold . s:italicize_comments)\n\nhi! link vimNotation GruvboxOrange\nhi! link vimBracket GruvboxOrange\nhi! link vimMapModKey GruvboxOrange\nhi! link vimFuncSID GruvboxFg3\nhi! link vimSetSep GruvboxFg3\nhi! link vimSep GruvboxFg3\nhi! link vimContinue GruvboxFg3\n\n\" }}}\n\" Clojure: {{{\n\nhi! link clojureKeyword GruvboxBlue\nhi! link clojureCond GruvboxOrange\nhi! link clojureSpecial GruvboxOrange\nhi! link clojureDefine GruvboxOrange\n\nhi! link clojureFunc GruvboxYellow\nhi! link clojureRepeat GruvboxYellow\nhi! link clojureCharacter GruvboxAqua\nhi! link clojureStringEscape GruvboxAqua\nhi! link clojureException GruvboxRed\n\nhi! link clojureRegexp GruvboxAqua\nhi! link clojureRegexpEscape GruvboxAqua\ncall s:HL('clojureRegexpCharClass', s:fg3, s:none, s:bold)\nhi! link clojureRegexpMod clojureRegexpCharClass\nhi! link clojureRegexpQuantifier clojureRegexpCharClass\n\nhi! link clojureParen GruvboxFg3\nhi! link clojureAnonArg GruvboxYellow\nhi! link clojureVariable GruvboxBlue\nhi! link clojureMacro GruvboxOrange\n\nhi! link clojureMeta GruvboxYellow\nhi! link clojureDeref GruvboxYellow\nhi! link clojureQuote GruvboxYellow\nhi! link clojureUnquote GruvboxYellow\n\n\" }}}\n\" C: {{{\n\nhi! link cOperator GruvboxPurple\nhi! link cStructure GruvboxOrange\n\n\" }}}\n\" Python: {{{\n\nhi! link pythonBuiltin GruvboxOrange\nhi! link pythonBuiltinObj GruvboxOrange\nhi! link pythonBuiltinFunc GruvboxOrange\nhi! link pythonFunction GruvboxAqua\nhi! link pythonDecorator GruvboxRed\nhi! link pythonInclude GruvboxBlue\nhi! link pythonImport GruvboxBlue\nhi! link pythonRun GruvboxBlue\nhi! link pythonCoding GruvboxBlue\nhi! link pythonOperator GruvboxRed\nhi! link pythonException GruvboxRed\nhi! link pythonExceptions GruvboxPurple\nhi! link pythonBoolean GruvboxPurple\nhi! link pythonDot GruvboxFg3\nhi! link pythonConditional GruvboxRed\nhi! link pythonRepeat GruvboxRed\nhi! link pythonDottedName GruvboxGreenBold\n\n\" }}}\n\" CSS: {{{\n\nhi! link cssBraces GruvboxBlue\nhi! link cssFunctionName GruvboxYellow\nhi! link cssIdentifier GruvboxOrange\nhi! link cssClassName GruvboxGreen\nhi! link cssColor GruvboxBlue\nhi! link cssSelectorOp GruvboxBlue\nhi! link cssSelectorOp2 GruvboxBlue\nhi! link cssImportant GruvboxGreen\nhi! link cssVendor GruvboxFg1\n\nhi! link cssTextProp GruvboxAqua\nhi! link cssAnimationProp GruvboxAqua\nhi! link cssUIProp GruvboxYellow\nhi! link cssTransformProp GruvboxAqua\nhi! link cssTransitionProp GruvboxAqua\nhi! link cssPrintProp GruvboxAqua\nhi! link cssPositioningProp GruvboxYellow\nhi! link cssBoxProp GruvboxAqua\nhi! link cssFontDescriptorProp GruvboxAqua\nhi! link cssFlexibleBoxProp GruvboxAqua\nhi! link cssBorderOutlineProp GruvboxAqua\nhi! link cssBackgroundProp GruvboxAqua\nhi! link cssMarginProp GruvboxAqua\nhi! link cssListProp GruvboxAqua\nhi! link cssTableProp GruvboxAqua\nhi! link cssFontProp GruvboxAqua\nhi! link cssPaddingProp GruvboxAqua\nhi! link cssDimensionProp GruvboxAqua\nhi! link cssRenderProp GruvboxAqua\nhi! link cssColorProp GruvboxAqua\nhi! link cssGeneratedContentProp GruvboxAqua\n\n\" }}}\n\" JavaScript: {{{\n\nhi! link javaScriptBraces GruvboxFg1\nhi! link javaScriptFunction GruvboxAqua\nhi! link javaScriptIdentifier GruvboxRed\nhi! link javaScriptMember GruvboxBlue\nhi! link javaScriptNumber GruvboxPurple\nhi! link javaScriptNull GruvboxPurple\nhi! link javaScriptParens GruvboxFg3\n\n\" }}}\n\" YAJS: {{{\n\nhi! link javascriptImport GruvboxAqua\nhi! link javascriptExport GruvboxAqua\nhi! link javascriptClassKeyword GruvboxAqua\nhi! link javascriptClassExtends GruvboxAqua\nhi! link javascriptDefault GruvboxAqua\n\nhi! link javascriptClassName GruvboxYellow\nhi! link javascriptClassSuperName GruvboxYellow\nhi! link javascriptGlobal GruvboxYellow\n\nhi! link javascriptEndColons GruvboxFg1\nhi! link javascriptFuncArg GruvboxFg1\nhi! link javascriptGlobalMethod GruvboxFg1\nhi! link javascriptNodeGlobal GruvboxFg1\nhi! link javascriptBOMWindowProp GruvboxFg1\nhi! link javascriptArrayMethod GruvboxFg1\nhi! link javascriptArrayStaticMethod GruvboxFg1\nhi! link javascriptCacheMethod GruvboxFg1\nhi! link javascriptDateMethod GruvboxFg1\nhi! link javascriptMathStaticMethod GruvboxFg1\n\n\" hi! link javascriptProp GruvboxFg1\nhi! link javascriptURLUtilsProp GruvboxFg1\nhi! link javascriptBOMNavigatorProp GruvboxFg1\nhi! link javascriptDOMDocMethod GruvboxFg1\nhi! link javascriptDOMDocProp GruvboxFg1\nhi! link javascriptBOMLocationMethod GruvboxFg1\nhi! link javascriptBOMWindowMethod GruvboxFg1\nhi! link javascriptStringMethod GruvboxFg1\n\nhi! link javascriptVariable GruvboxOrange\n\" hi! link javascriptVariable GruvboxRed\n\" hi! link javascriptIdentifier GruvboxOrange\n\" hi! link javascriptClassSuper GruvboxOrange\nhi! link javascriptIdentifier GruvboxOrange\nhi! link javascriptClassSuper GruvboxOrange\n\n\" hi! link javascriptFuncKeyword GruvboxOrange\n\" hi! link javascriptAsyncFunc GruvboxOrange\nhi! link javascriptFuncKeyword GruvboxAqua\nhi! link javascriptAsyncFunc GruvboxAqua\nhi! link javascriptClassStatic GruvboxOrange\n\nhi! link javascriptOperator GruvboxRed\nhi! link javascriptForOperator GruvboxRed\nhi! link javascriptYield GruvboxRed\nhi! link javascriptExceptions GruvboxRed\nhi! link javascriptMessage GruvboxRed\n\nhi! link javascriptTemplateSB GruvboxAqua\nhi! link javascriptTemplateSubstitution GruvboxFg1\n\n\" hi! link javascriptLabel GruvboxBlue\n\" hi! link javascriptObjectLabel GruvboxBlue\n\" hi! link javascriptPropertyName GruvboxBlue\nhi! link javascriptLabel GruvboxFg1\nhi! link javascriptObjectLabel GruvboxFg1\nhi! link javascriptPropertyName GruvboxFg1\n\nhi! link javascriptLogicSymbols GruvboxFg1\nhi! link javascriptArrowFunc GruvboxYellow\n\nhi! link javascriptDocParamName GruvboxFg4\nhi! link javascriptDocTags GruvboxFg4\nhi! link javascriptDocNotation GruvboxFg4\nhi! link javascriptDocParamType GruvboxFg4\nhi! link javascriptDocNamedParamType GruvboxFg4\n\nhi! link javascriptBrackets GruvboxFg1\nhi! link javascriptDOMElemAttrs GruvboxFg1\nhi! link javascriptDOMEventMethod GruvboxFg1\nhi! link javascriptDOMNodeMethod GruvboxFg1\nhi! link javascriptDOMStorageMethod GruvboxFg1\nhi! link javascriptHeadersMethod GruvboxFg1\n\nhi! link javascriptAsyncFuncKeyword GruvboxRed\nhi! link javascriptAwaitFuncKeyword GruvboxRed\n\n\" }}}\n\" PanglossJS: {{{\n\nhi! link jsClassKeyword GruvboxAqua\nhi! link jsExtendsKeyword GruvboxAqua\nhi! link jsExportDefault GruvboxAqua\nhi! link jsTemplateBraces GruvboxAqua\nhi! link jsGlobalNodeObjects GruvboxFg1\nhi! link jsGlobalObjects GruvboxFg1\nhi! link jsFunction GruvboxAqua\nhi! link jsFuncParens GruvboxFg3\nhi! link jsParens GruvboxFg3\nhi! link jsNull GruvboxPurple\nhi! link jsUndefined GruvboxPurple\nhi! link jsClassDefinition GruvboxYellow\n\n\" }}}\n\" TypeScript: {{{\n\nhi! link typeScriptReserved GruvboxAqua\nhi! link typeScriptLabel GruvboxAqua\nhi! link typeScriptFuncKeyword GruvboxAqua\nhi! link typeScriptIdentifier GruvboxOrange\nhi! link typeScriptBraces GruvboxFg1\nhi! link typeScriptEndColons GruvboxFg1\nhi! link typeScriptDOMObjects GruvboxFg1\nhi! link typeScriptAjaxMethods GruvboxFg1\nhi! link typeScriptLogicSymbols GruvboxFg1\nhi! link typeScriptDocSeeTag Comment\nhi! link typeScriptDocParam Comment\nhi! link typeScriptDocTags vimCommentTitle\nhi! link typeScriptGlobalObjects GruvboxFg1\nhi! link typeScriptParens GruvboxFg3\nhi! link typeScriptOpSymbols GruvboxFg3\nhi! link typeScriptHtmlElemProperties GruvboxFg1\nhi! link typeScriptNull GruvboxPurple\nhi! link typeScriptInterpolationDelimiter GruvboxAqua\n\n\" }}}\n\" PureScript: {{{\n\nhi! link purescriptModuleKeyword GruvboxAqua\nhi! link purescriptModuleName GruvboxFg1\nhi! link purescriptWhere GruvboxAqua\nhi! link purescriptDelimiter GruvboxFg4\nhi! link purescriptType GruvboxFg1\nhi! link purescriptImportKeyword GruvboxAqua\nhi! link purescriptHidingKeyword GruvboxAqua\nhi! link purescriptAsKeyword GruvboxAqua\nhi! link purescriptStructure GruvboxAqua\nhi! link purescriptOperator GruvboxBlue\n\nhi! link purescriptTypeVar GruvboxFg1\nhi! link purescriptConstructor GruvboxFg1\nhi! link purescriptFunction GruvboxFg1\nhi! link purescriptConditional GruvboxOrange\nhi! link purescriptBacktick GruvboxOrange\n\n\" }}}\n\" CoffeeScript: {{{\n\nhi! link coffeeExtendedOp GruvboxFg3\nhi! link coffeeSpecialOp GruvboxFg3\nhi! link coffeeCurly GruvboxOrange\nhi! link coffeeParen GruvboxFg3\nhi! link coffeeBracket GruvboxOrange\n\n\" }}}\n\" Ruby: {{{\n\nhi! link rubyStringDelimiter GruvboxGreen\nhi! link rubyInterpolationDelimiter GruvboxAqua\n\n\" }}}\n\" ObjectiveC: {{{\n\nhi! link objcTypeModifier GruvboxRed\nhi! link objcDirective GruvboxBlue\n\n\" }}}\n\" Go: {{{\n\nhi! link goDirective GruvboxAqua\nhi! link goConstants GruvboxPurple\nhi! link goDeclaration GruvboxRed\nhi! link goDeclType GruvboxBlue\nhi! link goBuiltins GruvboxOrange\n\n\" }}}\n\" Lua: {{{\n\nhi! link luaIn GruvboxRed\nhi! link luaFunction GruvboxAqua\nhi! link luaTable GruvboxOrange\n\n\" }}}\n\" MoonScript: {{{\n\nhi! link moonSpecialOp GruvboxFg3\nhi! link moonExtendedOp GruvboxFg3\nhi! link moonFunction GruvboxFg3\nhi! link moonObject GruvboxYellow\n\n\" }}}\n\" Java: {{{\n\nhi! link javaAnnotation GruvboxBlue\nhi! link javaDocTags GruvboxAqua\nhi! link javaCommentTitle vimCommentTitle\nhi! link javaParen GruvboxFg3\nhi! link javaParen1 GruvboxFg3\nhi! link javaParen2 GruvboxFg3\nhi! link javaParen3 GruvboxFg3\nhi! link javaParen4 GruvboxFg3\nhi! link javaParen5 GruvboxFg3\nhi! link javaOperator GruvboxOrange\n\nhi! link javaVarArg GruvboxGreen\n\n\" }}}\n\" Elixir: {{{\n\nhi! link elixirDocString Comment\n\nhi! link elixirStringDelimiter GruvboxGreen\nhi! link elixirInterpolationDelimiter GruvboxAqua\n\nhi! link elixirModuleDeclaration GruvboxYellow\n\n\" }}}\n\" Scala: {{{\n\n\" NB: scala vim syntax file is kinda horrible\nhi! link scalaNameDefinition GruvboxFg1\nhi! link scalaCaseFollowing GruvboxFg1\nhi! link scalaCapitalWord GruvboxFg1\nhi! link scalaTypeExtension GruvboxFg1\n\nhi! link scalaKeyword GruvboxRed\nhi! link scalaKeywordModifier GruvboxRed\n\nhi! link scalaSpecial GruvboxAqua\nhi! link scalaOperator GruvboxFg1\n\nhi! link scalaTypeDeclaration GruvboxYellow\nhi! link scalaTypeTypePostDeclaration GruvboxYellow\n\nhi! link scalaInstanceDeclaration GruvboxFg1\nhi! link scalaInterpolation GruvboxAqua\n\n\" }}}\n\" Markdown: {{{\n\ncall s:HL('markdownItalic', s:fg3, s:none, s:italic)\n\nhi! link markdownH1 GruvboxGreenBold\nhi! link markdownH2 GruvboxGreenBold\nhi! link markdownH3 GruvboxYellowBold\nhi! link markdownH4 GruvboxYellowBold\nhi! link markdownH5 GruvboxYellow\nhi! link markdownH6 GruvboxYellow\n\nhi! link markdownCode GruvboxAqua\nhi! link markdownCodeBlock GruvboxAqua\nhi! link markdownCodeDelimiter GruvboxAqua\n\nhi! link markdownBlockquote GruvboxGray\nhi! link markdownListMarker GruvboxGray\nhi! link markdownOrderedListMarker GruvboxGray\nhi! link markdownRule GruvboxGray\nhi! link markdownHeadingRule GruvboxGray\n\nhi! link markdownUrlDelimiter GruvboxFg3\nhi! link markdownLinkDelimiter GruvboxFg3\nhi! link markdownLinkTextDelimiter GruvboxFg3\n\nhi! link markdownHeadingDelimiter GruvboxOrange\nhi! link markdownUrl GruvboxPurple\nhi! link markdownUrlTitleDelimiter GruvboxGreen\n\ncall s:HL('markdownLinkText', s:gray, s:none, s:underline)\nhi! link markdownIdDeclaration markdownLinkText\n\n\" }}}\n\" Haskell: {{{\n\n\" hi! link haskellType GruvboxYellow\n\" hi! link haskellOperators GruvboxOrange\n\" hi! link haskellConditional GruvboxAqua\n\" hi! link haskellLet GruvboxOrange\n\"\nhi! link haskellType GruvboxFg1\nhi! link haskellIdentifier GruvboxFg1\nhi! link haskellSeparator GruvboxFg1\nhi! link haskellDelimiter GruvboxFg4\nhi! link haskellOperators GruvboxBlue\n\"\nhi! link haskellBacktick GruvboxOrange\nhi! link haskellStatement GruvboxOrange\nhi! link haskellConditional GruvboxOrange\n\nhi! link haskellLet GruvboxAqua\nhi! link haskellDefault GruvboxAqua\nhi! link haskellWhere GruvboxAqua\nhi! link haskellBottom GruvboxAqua\nhi! link haskellBlockKeywords GruvboxAqua\nhi! link haskellImportKeywords GruvboxAqua\nhi! link haskellDeclKeyword GruvboxAqua\nhi! link haskellDeriving GruvboxAqua\nhi! link haskellAssocType GruvboxAqua\n\nhi! link haskellNumber GruvboxPurple\nhi! link haskellPragma GruvboxPurple\n\nhi! link haskellString GruvboxGreen\nhi! link haskellChar GruvboxGreen\n\n\" }}}\n\" Json: {{{\n\nhi! link jsonKeyword GruvboxGreen\nhi! link jsonQuote GruvboxGreen\nhi! link jsonBraces GruvboxFg1\nhi! link jsonString GruvboxFg1\n\n\" }}}\n\n\n\" Functions -------------------------------------------------------------------\n\" Search Highlighting Cursor {{{\n\nfunction! GruvboxHlsShowCursor()\n  call s:HL('Cursor', s:bg0, s:hls_cursor)\nendfunction\n\nfunction! GruvboxHlsHideCursor()\n  call s:HL('Cursor', s:none, s:none, s:inverse)\nendfunction\n\n\" }}}\n\n\" vim: set sw=2 ts=2 sts=2 et tw=80 ft=vim fdm=marker:\n"
  },
  {
    "path": "extensions/theme-gruvbox/colors/gruvbox_dark.json",
    "content": "{\n    \"name\": \"gruvbox_dark\",\n    \"baseVimTheme\": \"gruvbox\",\n    \"baseVimBackground\": \"dark\",\n    \"colors\": {\n        \"background\": \"#1d2021\",\n        \"foreground\": \"#ebdbb2\",\n\n        \"title.background\": \"#1d2021\",\n        \"title.foreground\": \"#ebdbb2\",\n\n        \"editor.background\": \"#282828\",\n        \"editor.foreground\": \"#ebdbb2\",\n\n        \"tabs.background\": \"#3c3836\",\n        \"tabs.foreground\": \"#fbf1c7\",\n\n        \"toolTip.background\": \"#3c3836\",\n        \"toolTip.foreground\": \"#fbf1c7\",\n        \"toolTip.border\": \"#504945\",\n\n        \"menu.background\": \"#3c3836\",\n        \"menu.foreground\": \"#fbf1c7\",\n        \"menu.border\": \"#504945\",\n\n        \"contextMenu.background\": \"#3c3836\",\n        \"contextMenu.foreground\": \"#fbf1c7\",\n        \"contextMenu.border\": \"#504945\",\n        \"contextMenu.highlight\": \"#504945\",\n\n        \"statusBar.background\": \"#1d2021\",\n        \"statusBar.foreground\": \"#ebdbb2\",\n\n        \"highlight.mode.insert.background\": \"#83a598\",\n        \"highlight.mode.insert.foreground\": \"#282828\",\n\n        \"highlight.mode.normal.background\": \"#928374\",\n        \"highlight.mode.normal.foreground\": \"#282828\",\n\n        \"highlight.mode.operator.background\": \"#d3869b\",\n        \"highlight.mode.operator.foreground\": \"#282828\",\n\n        \"highlight.mode.visual.background\": \"#fe8019\",\n        \"highlight.mode.visual.foreground\": \"#282828\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-gruvbox/colors/gruvbox_light.json",
    "content": "{\n    \"name\": \"gruvbox_light\",\n    \"baseVimTheme\": \"gruvbox\",\n    \"baseVimBackground\": \"light\",\n    \"colors\": {\n        \"background\": \"#f9f5d7\",\n        \"foreground\": \"#3c3836\",\n\n        \"title.background\": \"#f9f5d7\",\n        \"title.foreground\": \"#3c3836\",\n\n        \"editor.background\": \"#fbf1c7\",\n        \"editor.foreground\": \"#3c3836\",\n\n        \"tabs.background\": \"#ebdbb2\",\n        \"tabs.foreground\": \"#282828\",\n\n        \"toolTip.background\": \"#fbf1c7\",\n        \"toolTip.foreground\": \"#282828\",\n        \"toolTip.border\": \"#d5c4a1\",\n\n        \"menu.background\": \"#fbf1c7\",\n        \"menu.foreground\": \"#282828\",\n        \"menu.border\": \"#d5c4a1\",\n\n        \"contextMenu.background\": \"#fbf1c7\",\n        \"contextMenu.foreground\": \"#282828\",\n        \"contextMenu.border\": \"#d5c4a1\",\n        \"contextMenu.highlight\": \"#d5c4a1\",\n\n        \"statusBar.background\": \"#f9f5d7\",\n        \"statusBar.foreground\": \"#3c3836\",\n\n        \"highlight.mode.insert.background\": \"#076678\",\n        \"highlight.mode.insert.foreground\": \"#fbf1c7\",\n\n        \"highlight.mode.normal.background\": \"#928374\",\n        \"highlight.mode.normal.foreground\": \"#fbf1c7\",\n\n        \"highlight.mode.operator.background\": \"#8f3f71\",\n        \"highlight.mode.operator.foreground\": \"#fbf1c7\",\n\n        \"highlight.mode.visual.background\": \"#d65d0e\",\n        \"highlight.mode.visual.foreground\": \"#fbf1c7\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-gruvbox/package.json",
    "content": "{\n  \"name\": \"onivim-theme-gruvbox\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Gruvbox theme, ported to Oni\",\n  \"engines\": {\n    \"oni\": \"0.3.2\"\n  },\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"contributes\": {\n    \"themes\": [\n      {\n        \"name\": \"gruvbox_dark\",\n        \"path\": \"colors/gruvbox_dark.json\"\n      },\n      {\n        \"name\": \"gruvbox_light\",\n        \"path\": \"colors/gruvbox_light.json\"\n      }\n    ]\n  },\n  \"author\": \"Parker Ault\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/theme-hybrid/colors/hybrid.vim",
    "content": "\" File:       hybrid.vim\n\" Maintainer: Andrew Wong (w0ng)\n\" URL:        https://github.com/w0ng/vim-hybrid\n\" Modified:   27 Jan 2013 07:33 AM AEST\n\" License:    MIT\n\n\" Description:\"{{{\n\" ----------------------------------------------------------------------------\n\" The default RGB colour palette is taken from Tomorrow-Night.vim:\n\" https://github.com/chriskempson/vim-tomorrow-theme\n\"\n\" The reduced RGB colour palette is taken from Codecademy's online editor:\n\" https://www.codecademy.com/learn\n\"\n\" The syntax highlighting scheme is taken from jellybeans.vim:\n\" https://github.com/nanotech/jellybeans.vim\n\"\n\" The is code taken from solarized.vim:\n\" https://github.com/altercation/vim-colors-solarized\n\n\"}}}\n\" Requirements And Recommendations:\"{{{\n\" ----------------------------------------------------------------------------\n\" Requirements\n\"   - gVim 7.3+ on Linux, Mac and Windows.\n\"   - Vim 7.3+ on Linux and Mac, using a terminal that supports 256 colours.\n\"\n\" Due to the limited 256 palette, colours in Vim and gVim will still be slightly\n\" different.\n\"\n\" In order to have Vim use the same colours as gVim (the way this colour scheme\n\" is intended), it is recommended that you define the basic 16 colours in your\n\" terminal.\n\"\n\" For Linux users (rxvt-unicode, xterm):\n\"\n\" 1.  Add the default palette to ~/.Xresources:\n\"\n\"         https://gist.github.com/3278077\n\"\n\"     or alternatively, add the reduced contrast palette to ~/.Xresources:\n\"\n\"         https://gist.github.com/w0ng/16e33902508b4a0350ae\n\"\n\" 2.  Add to ~/.vimrc:\n\"\n\"         let g:hybrid_custom_term_colors = 1\n\"         let g:hybrid_reduced_contrast = 1 \" Remove this line if using the default palette.\n\"         colorscheme hybrid\n\"\n\" For OSX users (iTerm):\n\"\n\" 1.  Import the default colour preset into iTerm:\n\"\n\"         https://raw.githubusercontent.com/w0ng/dotfiles/master/iterm2/hybrid.itermcolors\n\"\n\"     or alternatively, import the reduced contrast color preset into iTerm:\n\"\n\"         https://raw.githubusercontent.com/w0ng/dotfiles/master/iterm2/hybrid-reduced-contrast.itermcolors\n\"\n\" 2.  Add to ~/.vimrc:\n\"\n\"         let g:hybrid_custom_term_colors = 1\n\"         let g:hybrid_reduced_contrast = 1 \" Remove this line if using the default palette.\n\"         colorscheme hybrid\n\n\"}}}\n\" Initialisation:\"{{{\n\" ----------------------------------------------------------------------------\n\nhi clear\n\nif exists(\"syntax_on\")\n  syntax reset\nendif\n\nlet s:style = &background\n\nlet g:colors_name = \"hybrid\"\n\n\"}}}\n\" GUI And Cterm Palettes:\"{{{\n\" ----------------------------------------------------------------------------\n\nlet s:palette = {'gui' : {} , 'cterm' : {}}\n\nif exists(\"g:hybrid_reduced_contrast\") && g:hybrid_reduced_contrast == 1\n  let s:gui_background = \"#232c31\"\n  let s:gui_selection  = \"#425059\"\n  let s:gui_line       = \"#2d3c46\"\n  let s:gui_comment    = \"#6c7a80\"\nelse\n  let s:gui_background = \"#1d1f21\"\n  let s:gui_selection  = \"#373b41\"\n  let s:gui_line       = \"#282a2e\"\n  let s:gui_comment    = \"#707880\"\nendif\n\nlet s:palette.gui.background = { 'dark' : s:gui_background , 'light' : \"#e4e4e4\" }\nlet s:palette.gui.foreground = { 'dark' : \"#c5c8c6\"        , 'light' : \"#000000\" }\nlet s:palette.gui.selection  = { 'dark' : s:gui_selection  , 'light' : \"#bcbcbc\" }\nlet s:palette.gui.line       = { 'dark' : s:gui_line       , 'light' : \"#d0d0d0\" }\nlet s:palette.gui.comment    = { 'dark' : s:gui_comment    , 'light' : \"#5f5f5f\" }\nlet s:palette.gui.red        = { 'dark' : \"#cc6666\"        , 'light' : \"#5f0000\" }\nlet s:palette.gui.orange     = { 'dark' : \"#de935f\"        , 'light' : \"#875f00\" }\nlet s:palette.gui.yellow     = { 'dark' : \"#f0c674\"        , 'light' : \"#5f5f00\" }\nlet s:palette.gui.green      = { 'dark' : \"#b5bd68\"        , 'light' : \"#005f00\" }\nlet s:palette.gui.aqua       = { 'dark' : \"#8abeb7\"        , 'light' : \"#005f5f\" }\nlet s:palette.gui.blue       = { 'dark' : \"#81a2be\"        , 'light' : \"#00005f\" }\nlet s:palette.gui.purple     = { 'dark' : \"#b294bb\"        , 'light' : \"#5f005f\" }\nlet s:palette.gui.window     = { 'dark' : \"#303030\"        , 'light' : \"#9e9e9e\" }\nlet s:palette.gui.darkcolumn = { 'dark' : \"#1c1c1c\"        , 'light' : \"#808080\" }\nlet s:palette.gui.addbg      = { 'dark' : \"#5F875F\"        , 'light' : \"#d7ffd7\" }\nlet s:palette.gui.addfg      = { 'dark' : \"#d7ffaf\"        , 'light' : \"#005f00\" }\nlet s:palette.gui.changebg   = { 'dark' : \"#5F5F87\"        , 'light' : \"#d7d7ff\" }\nlet s:palette.gui.changefg   = { 'dark' : \"#d7d7ff\"        , 'light' : \"#5f005f\" }\nlet s:palette.gui.delbg      = { 'dark' : \"#cc6666\"        , 'light' : \"#ffd7d7\" }\nlet s:palette.gui.darkblue   = { 'dark' : \"#00005f\"        , 'light' : \"#d7ffd7\" }\nlet s:palette.gui.darkcyan   = { 'dark' : \"#005f5f\"        , 'light' : \"#005f00\" }\nlet s:palette.gui.darkred    = { 'dark' : \"#5f0000\"        , 'light' : \"#d7d7ff\" }\nlet s:palette.gui.darkpurple = { 'dark' : \"#5f005f\"        , 'light' : \"#5f005f\" }\n\nif exists(\"g:hybrid_custom_term_colors\") && g:hybrid_custom_term_colors == 1\n  let s:cterm_foreground = \"15\"  \" White\n  let s:cterm_selection  = \"8\"   \" DarkGrey\n  let s:cterm_line       = \"0\"   \" Black\n  let s:cterm_comment    = \"7\"   \" LightGrey\n  let s:cterm_red        = \"9\"   \" LightRed\n  let s:cterm_orange     = \"3\"   \" DarkYellow\n  let s:cterm_yellow     = \"11\"  \" LightYellow\n  let s:cterm_green      = \"10\"  \" LightGreen\n  let s:cterm_aqua       = \"14\"  \" LightCyan\n  let s:cterm_blue       = \"12\"  \" LightBlue\n  let s:cterm_purple     = \"13\"  \" LightMagenta\n  let s:cterm_delbg      = \"9\"   \" LightRed\nelse\n  let s:cterm_foreground = \"250\"\n  let s:cterm_selection  = \"237\"\n  let s:cterm_line       = \"235\"\n  let s:cterm_comment    = \"243\"\n  let s:cterm_red        = \"167\"\n  let s:cterm_orange     = \"173\"\n  let s:cterm_yellow     = \"221\"\n  let s:cterm_green      = \"143\"\n  let s:cterm_aqua       = \"109\"\n  let s:cterm_blue       = \"110\"\n  let s:cterm_purple     = \"139\"\n  let s:cterm_delbg      = \"167\"\nendif\n\nlet s:palette.cterm.background = { 'dark' : \"234\"              , 'light' : \"254\" }\nlet s:palette.cterm.foreground = { 'dark' : s:cterm_foreground , 'light' : \"16\"  }\nlet s:palette.cterm.window     = { 'dark' : \"236\"              , 'light' : \"247\" }\nlet s:palette.cterm.selection  = { 'dark' : s:cterm_selection  , 'light' : \"250\" }\nlet s:palette.cterm.line       = { 'dark' : s:cterm_line       , 'light' : \"252\" }\nlet s:palette.cterm.comment    = { 'dark' : s:cterm_comment    , 'light' : \"59\"  }\nlet s:palette.cterm.red        = { 'dark' : s:cterm_red        , 'light' : \"52\"  }\nlet s:palette.cterm.orange     = { 'dark' : s:cterm_orange     , 'light' : \"94\"  }\nlet s:palette.cterm.yellow     = { 'dark' : s:cterm_yellow     , 'light' : \"58\"  }\nlet s:palette.cterm.green      = { 'dark' : s:cterm_green      , 'light' : \"22\"  }\nlet s:palette.cterm.aqua       = { 'dark' : s:cterm_aqua       , 'light' : \"23\"  }\nlet s:palette.cterm.blue       = { 'dark' : s:cterm_blue       , 'light' : \"17\"  }\nlet s:palette.cterm.purple     = { 'dark' : s:cterm_purple     , 'light' : \"53\"  }\nlet s:palette.cterm.darkcolumn = { 'dark' : \"234\"              , 'light' : \"244\" }\nlet s:palette.cterm.addbg      = { 'dark' : \"65\"               , 'light' : \"194\" }\nlet s:palette.cterm.addfg      = { 'dark' : \"193\"              , 'light' : \"22\"  }\nlet s:palette.cterm.changebg   = { 'dark' : \"60\"               , 'light' : \"189\" }\nlet s:palette.cterm.changefg   = { 'dark' : \"189\"              , 'light' : \"53\"  }\nlet s:palette.cterm.delbg      = { 'dark' : s:cterm_delbg      , 'light' : \"224\" }\nlet s:palette.cterm.darkblue   = { 'dark' : \"17\"               , 'light' : \"194\" }\nlet s:palette.cterm.darkcyan   = { 'dark' : \"24\"               , 'light' : \"22\"  }\nlet s:palette.cterm.darkred    = { 'dark' : \"52\"               , 'light' : \"189\" }\nlet s:palette.cterm.darkpurple = { 'dark' : \"53\"               , 'light' : \"53\"  }\n\n\"}}}\n\" Formatting Options:\"{{{\n\" ----------------------------------------------------------------------------\nlet s:none   = \"NONE\"\nlet s:t_none = \"NONE\"\nlet s:n      = \"NONE\"\nlet s:c      = \",undercurl\"\nlet s:r      = \",reverse\"\nlet s:s      = \",standout\"\nlet s:b      = \",bold\"\nlet s:u      = \",underline\"\nlet s:i      = \",italic\"\n\n\"}}}\n\" Highlighting Primitives:\"{{{\n\" ----------------------------------------------------------------------------\nfunction! s:build_prim(hi_elem, field)\n  \" Given a:hi_elem = bg, a:field = comment\n  let l:vname = \"s:\" . a:hi_elem . \"_\" . a:field \" s:bg_comment\n  let l:gui_assign = \"gui\".a:hi_elem.\"=\".s:palette.gui[a:field][s:style] \" guibg=...\n  let l:cterm_assign = \"cterm\".a:hi_elem.\"=\".s:palette.cterm[a:field][s:style] \" ctermbg=...\n  exe \"let \" . l:vname . \" = ' \" . l:gui_assign . \" \" . l:cterm_assign . \"'\"\nendfunction\n\nlet s:bg_none = ' guibg=NONE ctermbg=NONE'\ncall s:build_prim('bg', 'foreground')\ncall s:build_prim('bg', 'background')\ncall s:build_prim('bg', 'selection')\ncall s:build_prim('bg', 'line')\ncall s:build_prim('bg', 'comment')\ncall s:build_prim('bg', 'red')\ncall s:build_prim('bg', 'orange')\ncall s:build_prim('bg', 'yellow')\ncall s:build_prim('bg', 'green')\ncall s:build_prim('bg', 'aqua')\ncall s:build_prim('bg', 'blue')\ncall s:build_prim('bg', 'purple')\ncall s:build_prim('bg', 'window')\ncall s:build_prim('bg', 'darkcolumn')\ncall s:build_prim('bg', 'addbg')\ncall s:build_prim('bg', 'addfg')\ncall s:build_prim('bg', 'changebg')\ncall s:build_prim('bg', 'changefg')\ncall s:build_prim('bg', 'delbg')\ncall s:build_prim('bg', 'darkblue')\ncall s:build_prim('bg', 'darkcyan')\ncall s:build_prim('bg', 'darkred')\ncall s:build_prim('bg', 'darkpurple')\n\nlet s:fg_none = ' guifg=NONE ctermfg=NONE'\ncall s:build_prim('fg', 'foreground')\ncall s:build_prim('fg', 'background')\ncall s:build_prim('fg', 'selection')\ncall s:build_prim('fg', 'line')\ncall s:build_prim('fg', 'comment')\ncall s:build_prim('fg', 'red')\ncall s:build_prim('fg', 'orange')\ncall s:build_prim('fg', 'yellow')\ncall s:build_prim('fg', 'green')\ncall s:build_prim('fg', 'aqua')\ncall s:build_prim('fg', 'blue')\ncall s:build_prim('fg', 'purple')\ncall s:build_prim('fg', 'window')\ncall s:build_prim('fg', 'darkcolumn')\ncall s:build_prim('fg', 'addbg')\ncall s:build_prim('fg', 'addfg')\ncall s:build_prim('fg', 'changebg')\ncall s:build_prim('fg', 'changefg')\ncall s:build_prim('fg', 'darkblue')\ncall s:build_prim('fg', 'darkcyan')\ncall s:build_prim('fg', 'darkred')\ncall s:build_prim('fg', 'darkpurple')\n\nexe \"let s:fmt_none = ' gui=NONE\".          \" cterm=NONE\".          \" term=NONE\"        .\"'\"\nexe \"let s:fmt_bold = ' gui=NONE\".s:b.      \" cterm=NONE\".s:b.      \" term=NONE\".s:b    .\"'\"\nexe \"let s:fmt_bldi = ' gui=NONE\".s:b.      \" cterm=NONE\".s:b.      \" term=NONE\".s:b    .\"'\"\nexe \"let s:fmt_undr = ' gui=NONE\".s:u.      \" cterm=NONE\".s:u.      \" term=NONE\".s:u    .\"'\"\nexe \"let s:fmt_undb = ' gui=NONE\".s:u.s:b.  \" cterm=NONE\".s:u.s:b.  \" term=NONE\".s:u.s:b.\"'\"\nexe \"let s:fmt_undi = ' gui=NONE\".s:u.      \" cterm=NONE\".s:u.      \" term=NONE\".s:u    .\"'\"\nexe \"let s:fmt_curl = ' gui=NONE\".s:c.      \" cterm=NONE\".s:c.      \" term=NONE\".s:c    .\"'\"\nexe \"let s:fmt_ital = ' gui=NONE\".s:i.      \" cterm=NONE\".s:i.      \" term=NONE\".s:i    .\"'\"\nexe \"let s:fmt_stnd = ' gui=NONE\".s:s.      \" cterm=NONE\".s:s.      \" term=NONE\".s:s    .\"'\"\nexe \"let s:fmt_revr = ' gui=NONE\".s:r.      \" cterm=NONE\".s:r.      \" term=NONE\".s:r    .\"'\"\nexe \"let s:fmt_revb = ' gui=NONE\".s:r.s:b.  \" cterm=NONE\".s:r.s:b.  \" term=NONE\".s:r.s:b.\"'\"\n\nexe \"let s:sp_none       = ' guisp=\". s:none                            .\"'\"\nexe \"let s:sp_foreground = ' guisp=\". s:palette.gui.foreground[s:style] .\"'\"\nexe \"let s:sp_background = ' guisp=\". s:palette.gui.background[s:style] .\"'\"\nexe \"let s:sp_selection  = ' guisp=\". s:palette.gui.selection[s:style]  .\"'\"\nexe \"let s:sp_line       = ' guisp=\". s:palette.gui.line[s:style]       .\"'\"\nexe \"let s:sp_comment    = ' guisp=\". s:palette.gui.comment[s:style]    .\"'\"\nexe \"let s:sp_red        = ' guisp=\". s:palette.gui.red[s:style]        .\"'\"\nexe \"let s:sp_orange     = ' guisp=\". s:palette.gui.orange[s:style]     .\"'\"\nexe \"let s:sp_yellow     = ' guisp=\". s:palette.gui.yellow[s:style]     .\"'\"\nexe \"let s:sp_green      = ' guisp=\". s:palette.gui.green[s:style]      .\"'\"\nexe \"let s:sp_aqua       = ' guisp=\". s:palette.gui.aqua[s:style]       .\"'\"\nexe \"let s:sp_blue       = ' guisp=\". s:palette.gui.blue[s:style]       .\"'\"\nexe \"let s:sp_purple     = ' guisp=\". s:palette.gui.purple[s:style]     .\"'\"\nexe \"let s:sp_window     = ' guisp=\". s:palette.gui.window[s:style]     .\"'\"\nexe \"let s:sp_addbg      = ' guisp=\". s:palette.gui.addbg[s:style]      .\"'\"\nexe \"let s:sp_addfg      = ' guisp=\". s:palette.gui.addfg[s:style]      .\"'\"\nexe \"let s:sp_changebg   = ' guisp=\". s:palette.gui.changebg[s:style]   .\"'\"\nexe \"let s:sp_changefg   = ' guisp=\". s:palette.gui.changefg[s:style]   .\"'\"\nexe \"let s:sp_darkblue   = ' guisp=\". s:palette.gui.darkblue[s:style]   .\"'\"\nexe \"let s:sp_darkcyan   = ' guisp=\". s:palette.gui.darkcyan[s:style]   .\"'\"\nexe \"let s:sp_darkred    = ' guisp=\". s:palette.gui.darkred[s:style]    .\"'\"\nexe \"let s:sp_darkpurple = ' guisp=\". s:palette.gui.darkpurple[s:style] .\"'\"\n\n\"}}}\n\" Vim Highlighting: (see :help highlight-groups)\"{{{\n\" ----------------------------------------------------------------------------\nexe \"hi! ColorColumn\"   .s:fg_none        .s:bg_line        .s:fmt_none\n\"   Conceal\"\n\"   Cursor\"\n\"   CursorIM\"\nexe \"hi! CursorColumn\"  .s:fg_none        .s:bg_line        .s:fmt_none\nexe \"hi! CursorLine\"    .s:fg_none        .s:bg_line        .s:fmt_none\nexe \"hi! Directory\"     .s:fg_blue        .s:bg_none        .s:fmt_none\nexe \"hi! DiffAdd\"       .s:fg_addfg       .s:bg_addbg       .s:fmt_none\nexe \"hi! DiffChange\"    .s:fg_changefg    .s:bg_changebg    .s:fmt_none\nexe \"hi! DiffDelete\"    .s:fg_background  .s:bg_delbg       .s:fmt_none\nexe \"hi! DiffText\"      .s:fg_background  .s:bg_blue        .s:fmt_none\nexe \"hi! ErrorMsg\"      .s:fg_background  .s:bg_red         .s:fmt_stnd\nexe \"hi! VertSplit\"     .s:fg_window      .s:bg_none        .s:fmt_none\nexe \"hi! Folded\"        .s:fg_comment     .s:bg_darkcolumn  .s:fmt_none\nexe \"hi! FoldColumn\"    .s:fg_none        .s:bg_darkcolumn  .s:fmt_none\nexe \"hi! SignColumn\"    .s:fg_none        .s:bg_darkcolumn  .s:fmt_none\n\"   Incsearch\"\nexe \"hi! LineNr\"        .s:fg_selection   .s:bg_none        .s:fmt_none\nexe \"hi! CursorLineNr\"  .s:fg_yellow      .s:bg_none        .s:fmt_none\nexe \"hi! MatchParen\"    .s:fg_background  .s:bg_changebg    .s:fmt_none\nexe \"hi! ModeMsg\"       .s:fg_green       .s:bg_none        .s:fmt_none\nexe \"hi! MoreMsg\"       .s:fg_green       .s:bg_none        .s:fmt_none\nexe \"hi! NonText\"       .s:fg_selection   .s:bg_none        .s:fmt_none\nexe \"hi! Pmenu\"         .s:fg_foreground  .s:bg_selection   .s:fmt_none\nexe \"hi! PmenuSel\"      .s:fg_foreground  .s:bg_selection   .s:fmt_revr\n\"   PmenuSbar\"\n\"   PmenuThumb\"\nexe \"hi! Question\"      .s:fg_green       .s:bg_none        .s:fmt_none\nexe \"hi! Search\"        .s:fg_background  .s:bg_yellow      .s:fmt_none\nexe \"hi! SpecialKey\"    .s:fg_selection   .s:bg_none        .s:fmt_none\nexe \"hi! SpellCap\"      .s:fg_blue        .s:bg_darkblue    .s:fmt_undr\nexe \"hi! SpellLocal\"    .s:fg_aqua        .s:bg_darkcyan    .s:fmt_undr\nexe \"hi! SpellBad\"      .s:fg_red         .s:bg_darkred     .s:fmt_undr\nexe \"hi! SpellRare\"     .s:fg_purple      .s:bg_darkpurple  .s:fmt_undr\nexe \"hi! StatusLine\"    .s:fg_comment     .s:bg_background  .s:fmt_revr\nexe \"hi! StatusLineNC\"  .s:fg_window      .s:bg_comment     .s:fmt_revr\nexe \"hi! TabLine\"       .s:fg_foreground  .s:bg_darkcolumn  .s:fmt_revr\n\"   TabLineFill\"\n\"   TabLineSel\"\nexe \"hi! Title\"         .s:fg_yellow      .s:bg_none        .s:fmt_none\nexe \"hi! Visual\"        .s:fg_none        .s:bg_selection   .s:fmt_none\n\"   VisualNos\"\nexe \"hi! WarningMsg\"    .s:fg_red         .s:bg_none        .s:fmt_none\n\" FIXME LongLineWarning to use variables instead of hardcoding\nhi LongLineWarning  guifg=NONE        guibg=#371F1C     gui=underline ctermfg=NONE        ctermbg=NONE        cterm=underline\n\"   WildMenu\"\n\n\" Use defined custom background colour for terminal Vim.\nif !has('gui_running') && exists(\"g:hybrid_custom_term_colors\") && g:hybrid_custom_term_colors == 1\n  let s:bg_normal = s:bg_none\nelse\n  let s:bg_normal = s:bg_background\nendif\nexe \"hi! Normal\"        .s:fg_foreground  .s:bg_normal      .s:fmt_none\n\n\"}}}\n\" Generic Syntax Highlighting: (see :help group-name)\"{{{\n\" ----------------------------------------------------------------------------\nexe \"hi! Comment\"         .s:fg_comment     .s:bg_none        .s:fmt_none\n\nexe \"hi! Constant\"        .s:fg_red         .s:bg_none        .s:fmt_none\nexe \"hi! String\"          .s:fg_green       .s:bg_none        .s:fmt_none\n\"   Character\"\n\"   Number\"\n\"   Boolean\"\n\"   Float\"\n\nexe \"hi! Identifier\"      .s:fg_purple      .s:bg_none        .s:fmt_none\nexe \"hi! Function\"        .s:fg_yellow      .s:bg_none        .s:fmt_none\n\nexe \"hi! Statement\"       .s:fg_blue        .s:bg_none        .s:fmt_none\n\"   Conditional\"\n\"   Repeat\"\n\"   Label\"\nexe \"hi! Operator\"        .s:fg_aqua        .s:bg_none        .s:fmt_none\n\"   Keyword\"\n\"   Exception\"\n\nexe \"hi! PreProc\"         .s:fg_aqua        .s:bg_none        .s:fmt_none\n\"   Include\"\n\"   Define\"\n\"   Macro\"\n\"   PreCondit\"\n\nexe \"hi! Type\"            .s:fg_orange      .s:bg_none        .s:fmt_none\n\"   StorageClass\"\nexe \"hi! Structure\"       .s:fg_aqua        .s:bg_none        .s:fmt_none\n\"   Typedef\"\n\nexe \"hi! Special\"         .s:fg_green       .s:bg_none        .s:fmt_none\n\"   SpecialChar\"\n\"   Tag\"\n\"   Delimiter\"\n\"   SpecialComment\"\n\"   Debug\"\n\"\nexe \"hi! Underlined\"      .s:fg_blue        .s:bg_none        .s:fmt_none\n\nexe \"hi! Ignore\"          .s:fg_none        .s:bg_none        .s:fmt_none\n\nexe \"hi! Error\"           .s:fg_red         .s:bg_darkred     .s:fmt_undr\n\nexe \"hi! Todo\"            .s:fg_addfg       .s:bg_none        .s:fmt_none\n\n\" Quickfix window highlighting\nexe \"hi! qfLineNr\"        .s:fg_yellow      .s:bg_none        .s:fmt_none\n\"   qfFileName\"\n\"   qfLineNr\"\n\"   qfError\"\n\n\"}}}\n\" Diff Syntax Highlighting:\"{{{\n\" ----------------------------------------------------------------------------\n\" Diff\n\"   diffOldFile\n\"   diffNewFile\n\"   diffFile\n\"   diffOnly\n\"   diffIdentical\n\"   diffDiffer\n\"   diffBDiffer\n\"   diffIsA\n\"   diffNoEOL\n\"   diffCommon\nhi! link diffRemoved Constant\n\"   diffChanged\nhi! link diffAdded Special\n\"   diffLine\n\"   diffSubname\n\"   diffComment\n\n\"}}}\n\"\n\" This is needed for some reason: {{{\n\nlet &background = s:style\n\n\" }}}\n\" Legal:\"{{{\n\" ----------------------------------------------------------------------------\n\" Copyright (c) 2011 Ethan Schoonover\n\" Copyright (c) 2009-2012 NanoTech\n\" Copyright (c) 2012 w0ng\n\"\n\" Permission is hereby granted, free of charge, to any per‐\n\" son obtaining a copy of this software and associated doc‐\n\" umentation files (the “Software”), to deal in the Soft‐\n\" ware without restriction, including without limitation\n\" the rights to use, copy, modify, merge, publish, distrib‐\n\" ute, sublicense, and/or sell copies of the Software, and\n\" to permit persons to whom the Software is furnished to do\n\" so, subject to the following conditions:\n\"\n\" The above copyright notice and this permission notice\n\" shall be included in all copies or substantial portions\n\" of the Software.\n\"\n\" THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY\n\" KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\n\" THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICU‐\n\" LAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CON‐\n\" TRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON‐\n\" NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\" THE SOFTWARE.\n\n\" }}}\n"
  },
  {
    "path": "extensions/theme-hybrid/colors/hybrid_dark.json",
    "content": "{\n    \"name\": \"hybrid_dark\",\n    \"baseVimTheme\": \"hybrid\",\n    \"baseVimBackground\": \"dark\",\n    \"colors\": {\n        \"background\": \"#1d1f21\",\n        \"foreground\": \"#c5c8c6\",\n\n        \"title.background\": \"#1d1f21\",\n        \"title.foreground\": \"#c5c8c6\",\n\n        \"editor.background\": \"#1d1f21\",\n        \"editor.foreground\": \"#c5c8c6\",\n\n        \"tabs.background\": \"#232c31\",\n        \"tabs.foreground\": \"#c5c8c6\",\n\n        \"toolTip.background\": \"#232c31\",\n        \"toolTip.foreground\": \"#c5c8c6\",\n        \"toolTip.border\": \"#242d32\",\n\n        \"menu.background\": \"#232c31\",\n        \"menu.foreground\": \"#c5c8c6\",\n        \"menu.border\": \"#242d32\",\n\n        \"contextMenu.background\": \"#232c31\",\n        \"contextMenu.foreground\": \"#c5c8c6\",\n        \"contextMenu.border\": \"#242d32\",\n        \"contextMenu.highlight\": \"#373b41\",\n\n        \"statusBar.background\": \"#1d1f21\",\n        \"statusBar.foreground\": \"#c5c8c6\",\n\n        \"highlight.mode.insert.background\": \"#f0c674\",\n        \"highlight.mode.insert.foreground\": \"#1d1f21\",\n\n        \"highlight.mode.normal.background\": \"#81a2be\",\n        \"highlight.mode.normal.foreground\": \"#1d1f21\",\n\n        \"highlight.mode.operator.background\": \"#b294bb\",\n        \"highlight.mode.operator.foreground\": \"#1d1f21\",\n\n        \"highlight.mode.visual.background\": \"#b5bd68\",\n        \"highlight.mode.visual.foreground\": \"#1d1f21\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-hybrid/colors/hybrid_light.json",
    "content": "{\n    \"name\": \"hybrid_light\",\n    \"baseVimTheme\": \"hybrid\",\n    \"baseVimBackground\": \"light\",\n    \"colors\": {\n        \"background\": \"#e4e4e4\",\n        \"foreground\": \"#000000\",\n\n        \"title.background\": \"#e4e4e4\",\n        \"title.foreground\": \"#000000\",\n\n        \"editor.background\": \"#e4e4e4\",\n        \"editor.foreground\": \"#000000\",\n\n        \"tabs.background\": \"#d0d0d0\",\n        \"tabs.foreground\": \"#000000\",\n\n        \"toolTip.background\": \"#d0d0d0\",\n        \"toolTip.foreground\": \"#000000\",\n        \"toolTip.border\": \"#bcbcbc\",\n\n        \"menu.background\": \"#d0d0d0\",\n        \"menu.foreground\": \"#000000\",\n        \"menu.border\": \"#bcbcbc\",\n\n        \"contextMenu.background\": \"#d0d0d0\",\n        \"contextMenu.foreground\": \"#000000\",\n        \"contextMenu.border\": \"#bcbcbc\",\n        \"contextMenu.highlight\": \"#bcbcbc\",\n\n        \"statusBar.background\": \"#e4e4e4\",\n        \"statusBar.foreground\": \"#000000\",\n\n        \"highlight.mode.insert.background\": \"#5f5f00\",\n        \"highlight.mode.insert.foreground\": \"#e4e4e4\",\n\n        \"highlight.mode.normal.background\": \"#00005f\",\n        \"highlight.mode.normal.foreground\": \"#e4e4e4\",\n\n        \"highlight.mode.operator.background\": \"#5f005f\",\n        \"highlight.mode.operator.foreground\": \"#e4e4e4\",\n\n        \"highlight.mode.visual.background\": \"#005f00\",\n        \"highlight.mode.visual.foreground\": \"#e4e4e4\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-hybrid/package.json",
    "content": "{\n  \"name\": \"onivim-theme-hybrid\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Hybrid theme, ported to Oni\",\n  \"engines\": {\n    \"oni\": \"0.3.2\"\n  },\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"contributes\": {\n    \"themes\": [\n      {\n        \"name\": \"hybrid_dark\",\n        \"path\": \"colors/hybrid_dark.json\"\n      },\n      {\n        \"name\": \"hybrid_light\",\n        \"path\": \"colors/hybrid_light.json\"\n      }\n    ]\n  },\n  \"author\": \"Parker Ault\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/theme-icons-seti/README.md",
    "content": "The contents of this folder are based off of the 'theme-seti' used by VSCode:\nhttps://github.com/Microsoft/vscode/tree/master/extensions/theme-seti\n"
  },
  {
    "path": "extensions/theme-icons-seti/icons/seti-icon-theme.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been generated from data in https://github.com/jesseweed/seti-ui\",\n        \"- icon definitions: https://github.com/jesseweed/seti-ui/blob/master/styles/_fonts/seti.less\",\n        \"- icon colors: https://github.com/jesseweed/seti-ui/blob/master/styles/ui-variables.less\",\n        \"- file associations: https://github.com/jesseweed/seti-ui/blob/master/styles/components/icons/mapping.less\",\n        \"If you want to provide a fix or improvement, please create a pull request against the jesseweed/seti-ui repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"fonts\": [\n        {\n            \"id\": \"seti\",\n            \"src\": [\n                {\n                    \"path\": \"./seti.woff\",\n                    \"format\": \"woff\"\n                }\n            ],\n            \"weight\": \"normal\",\n            \"style\": \"normal\",\n            \"size\": \"150%\"\n        }\n    ],\n    \"iconDefinitions\": {\n        \"_R\": {\n            \"fontCharacter\": \"\\\\E001\"\n        },\n        \"_apple\": {\n            \"fontCharacter\": \"\\\\E002\"\n        },\n        \"_asm_light\": {\n            \"fontCharacter\": \"\\\\E003\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_asm\": {\n            \"fontCharacter\": \"\\\\E003\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_audio_light\": {\n            \"fontCharacter\": \"\\\\E004\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_audio\": {\n            \"fontCharacter\": \"\\\\E004\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_babel_light\": {\n            \"fontCharacter\": \"\\\\E005\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_babel\": {\n            \"fontCharacter\": \"\\\\E005\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_bower_light\": {\n            \"fontCharacter\": \"\\\\E006\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_bower\": {\n            \"fontCharacter\": \"\\\\E006\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_bsl_light\": {\n            \"fontCharacter\": \"\\\\E007\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_bsl\": {\n            \"fontCharacter\": \"\\\\E007\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_c-sharp_light\": {\n            \"fontCharacter\": \"\\\\E008\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_c-sharp\": {\n            \"fontCharacter\": \"\\\\E008\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_c_light\": {\n            \"fontCharacter\": \"\\\\E009\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_c\": {\n            \"fontCharacter\": \"\\\\E009\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_cake_light\": {\n            \"fontCharacter\": \"\\\\E00A\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_cake\": {\n            \"fontCharacter\": \"\\\\E00A\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_cake_php_light\": {\n            \"fontCharacter\": \"\\\\E00B\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_cake_php\": {\n            \"fontCharacter\": \"\\\\E00B\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_checkbox-unchecked\": {\n            \"fontCharacter\": \"\\\\E00C\"\n        },\n        \"_checkbox\": {\n            \"fontCharacter\": \"\\\\E00D\"\n        },\n        \"_cjsx\": {\n            \"fontCharacter\": \"\\\\E00E\"\n        },\n        \"_clock_light\": {\n            \"fontCharacter\": \"\\\\E00F\",\n            \"fontColor\": \"#627379\"\n        },\n        \"_clock\": {\n            \"fontCharacter\": \"\\\\E00F\",\n            \"fontColor\": \"#6d8086\"\n        },\n        \"_code-climate_light\": {\n            \"fontCharacter\": \"\\\\E010\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_code-climate\": {\n            \"fontCharacter\": \"\\\\E010\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_coffee_light\": {\n            \"fontCharacter\": \"\\\\E011\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_coffee\": {\n            \"fontCharacter\": \"\\\\E011\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_coffee_erb\": {\n            \"fontCharacter\": \"\\\\E012\"\n        },\n        \"_coldfusion_light\": {\n            \"fontCharacter\": \"\\\\E013\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_coldfusion\": {\n            \"fontCharacter\": \"\\\\E013\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_config_light\": {\n            \"fontCharacter\": \"\\\\E014\",\n            \"fontColor\": \"#627379\"\n        },\n        \"_config\": {\n            \"fontCharacter\": \"\\\\E014\",\n            \"fontColor\": \"#6d8086\"\n        },\n        \"_cpp_light\": {\n            \"fontCharacter\": \"\\\\E015\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_cpp\": {\n            \"fontCharacter\": \"\\\\E015\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_css_light\": {\n            \"fontCharacter\": \"\\\\E016\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_css\": {\n            \"fontCharacter\": \"\\\\E016\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_csv_light\": {\n            \"fontCharacter\": \"\\\\E017\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_csv\": {\n            \"fontCharacter\": \"\\\\E017\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_d_light\": {\n            \"fontCharacter\": \"\\\\E018\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_d\": {\n            \"fontCharacter\": \"\\\\E018\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_db_light\": {\n            \"fontCharacter\": \"\\\\E019\",\n            \"fontColor\": \"#dd4b78\"\n        },\n        \"_db\": {\n            \"fontCharacter\": \"\\\\E019\",\n            \"fontColor\": \"#f55385\"\n        },\n        \"_default_light\": {\n            \"fontCharacter\": \"\\\\E01A\",\n            \"fontColor\": \"#bfc2c1\"\n        },\n        \"_default\": {\n            \"fontCharacter\": \"\\\\E01A\",\n            \"fontColor\": \"#d4d7d6\"\n        },\n        \"_deprecation-cop\": {\n            \"fontCharacter\": \"\\\\E01B\"\n        },\n        \"_docker_light\": {\n            \"fontCharacter\": \"\\\\E01C\",\n            \"fontColor\": \"#dd4b78\"\n        },\n        \"_docker\": {\n            \"fontCharacter\": \"\\\\E01C\",\n            \"fontColor\": \"#f55385\"\n        },\n        \"_editorconfig\": {\n            \"fontCharacter\": \"\\\\E01D\"\n        },\n        \"_ejs_light\": {\n            \"fontCharacter\": \"\\\\E01E\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_ejs\": {\n            \"fontCharacter\": \"\\\\E01E\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_elixir_light\": {\n            \"fontCharacter\": \"\\\\E01F\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_elixir\": {\n            \"fontCharacter\": \"\\\\E01F\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_elixir_script_light\": {\n            \"fontCharacter\": \"\\\\E020\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_elixir_script\": {\n            \"fontCharacter\": \"\\\\E020\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_elm_light\": {\n            \"fontCharacter\": \"\\\\E021\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_elm\": {\n            \"fontCharacter\": \"\\\\E021\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_error\": {\n            \"fontCharacter\": \"\\\\E022\"\n        },\n        \"_eslint_light\": {\n            \"fontCharacter\": \"\\\\E023\",\n            \"fontColor\": \"#455155\"\n        },\n        \"_eslint\": {\n            \"fontCharacter\": \"\\\\E023\",\n            \"fontColor\": \"#4d5a5e\"\n        },\n        \"_f-sharp_light\": {\n            \"fontCharacter\": \"\\\\E024\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_f-sharp\": {\n            \"fontCharacter\": \"\\\\E024\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_favicon_light\": {\n            \"fontCharacter\": \"\\\\E025\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_favicon\": {\n            \"fontCharacter\": \"\\\\E025\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_firebase_light\": {\n            \"fontCharacter\": \"\\\\E026\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_firebase\": {\n            \"fontCharacter\": \"\\\\E026\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_firefox_light\": {\n            \"fontCharacter\": \"\\\\E027\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_firefox\": {\n            \"fontCharacter\": \"\\\\E027\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_folder\": {\n            \"fontCharacter\": \"\\\\E028\"\n        },\n        \"_font_light\": {\n            \"fontCharacter\": \"\\\\E029\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_font\": {\n            \"fontCharacter\": \"\\\\E029\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_git_light\": {\n            \"fontCharacter\": \"\\\\E02A\",\n            \"fontColor\": \"#3b4b52\"\n        },\n        \"_git\": {\n            \"fontCharacter\": \"\\\\E02A\",\n            \"fontColor\": \"#41535b\"\n        },\n        \"_git_folder\": {\n            \"fontCharacter\": \"\\\\E02B\"\n        },\n        \"_git_ignore\": {\n            \"fontCharacter\": \"\\\\E02C\"\n        },\n        \"_github\": {\n            \"fontCharacter\": \"\\\\E02D\"\n        },\n        \"_go_light\": {\n            \"fontCharacter\": \"\\\\E02E\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_go\": {\n            \"fontCharacter\": \"\\\\E02E\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_go2_light\": {\n            \"fontCharacter\": \"\\\\E02F\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_go2\": {\n            \"fontCharacter\": \"\\\\E02F\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_gradle_light\": {\n            \"fontCharacter\": \"\\\\E030\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_gradle\": {\n            \"fontCharacter\": \"\\\\E030\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_grails_light\": {\n            \"fontCharacter\": \"\\\\E031\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_grails\": {\n            \"fontCharacter\": \"\\\\E031\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_grunt_light\": {\n            \"fontCharacter\": \"\\\\E032\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_grunt\": {\n            \"fontCharacter\": \"\\\\E032\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_gulp_light\": {\n            \"fontCharacter\": \"\\\\E033\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_gulp\": {\n            \"fontCharacter\": \"\\\\E033\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_hacklang\": {\n            \"fontCharacter\": \"\\\\E034\"\n        },\n        \"_haml_light\": {\n            \"fontCharacter\": \"\\\\E035\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_haml\": {\n            \"fontCharacter\": \"\\\\E035\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_haskell_light\": {\n            \"fontCharacter\": \"\\\\E036\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_haskell\": {\n            \"fontCharacter\": \"\\\\E036\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_heroku_light\": {\n            \"fontCharacter\": \"\\\\E037\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_heroku\": {\n            \"fontCharacter\": \"\\\\E037\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_hex_light\": {\n            \"fontCharacter\": \"\\\\E038\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_hex\": {\n            \"fontCharacter\": \"\\\\E038\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_html_light\": {\n            \"fontCharacter\": \"\\\\E039\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_html\": {\n            \"fontCharacter\": \"\\\\E039\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_html_erb\": {\n            \"fontCharacter\": \"\\\\E03A\"\n        },\n        \"_ignored_light\": {\n            \"fontCharacter\": \"\\\\E03B\",\n            \"fontColor\": \"#3b4b52\"\n        },\n        \"_ignored\": {\n            \"fontCharacter\": \"\\\\E03B\",\n            \"fontColor\": \"#41535b\"\n        },\n        \"_illustrator_light\": {\n            \"fontCharacter\": \"\\\\E03C\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_illustrator\": {\n            \"fontCharacter\": \"\\\\E03C\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_image_light\": {\n            \"fontCharacter\": \"\\\\E03D\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_image\": {\n            \"fontCharacter\": \"\\\\E03D\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_info_light\": {\n            \"fontCharacter\": \"\\\\E03E\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_info\": {\n            \"fontCharacter\": \"\\\\E03E\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_ionic_light\": {\n            \"fontCharacter\": \"\\\\E03F\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_ionic\": {\n            \"fontCharacter\": \"\\\\E03F\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_jade_light\": {\n            \"fontCharacter\": \"\\\\E040\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_jade\": {\n            \"fontCharacter\": \"\\\\E040\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_java_light\": {\n            \"fontCharacter\": \"\\\\E041\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_java\": {\n            \"fontCharacter\": \"\\\\E041\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_javascript_light\": {\n            \"fontCharacter\": \"\\\\E042\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_javascript\": {\n            \"fontCharacter\": \"\\\\E042\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_jenkins_light\": {\n            \"fontCharacter\": \"\\\\E043\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_jenkins\": {\n            \"fontCharacter\": \"\\\\E043\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_jinja_light\": {\n            \"fontCharacter\": \"\\\\E044\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_jinja\": {\n            \"fontCharacter\": \"\\\\E044\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_js_erb\": {\n            \"fontCharacter\": \"\\\\E045\"\n        },\n        \"_json_light\": {\n            \"fontCharacter\": \"\\\\E046\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_json\": {\n            \"fontCharacter\": \"\\\\E046\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_julia_light\": {\n            \"fontCharacter\": \"\\\\E047\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_julia\": {\n            \"fontCharacter\": \"\\\\E047\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_karma_light\": {\n            \"fontCharacter\": \"\\\\E048\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_karma\": {\n            \"fontCharacter\": \"\\\\E048\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_less_light\": {\n            \"fontCharacter\": \"\\\\E049\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_less\": {\n            \"fontCharacter\": \"\\\\E049\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_license_light\": {\n            \"fontCharacter\": \"\\\\E04A\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_license\": {\n            \"fontCharacter\": \"\\\\E04A\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_liquid_light\": {\n            \"fontCharacter\": \"\\\\E04B\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_liquid\": {\n            \"fontCharacter\": \"\\\\E04B\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_livescript_light\": {\n            \"fontCharacter\": \"\\\\E04C\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_livescript\": {\n            \"fontCharacter\": \"\\\\E04C\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_lock_light\": {\n            \"fontCharacter\": \"\\\\E04D\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_lock\": {\n            \"fontCharacter\": \"\\\\E04D\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_lua_light\": {\n            \"fontCharacter\": \"\\\\E04E\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_lua\": {\n            \"fontCharacter\": \"\\\\E04E\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_makefile_light\": {\n            \"fontCharacter\": \"\\\\E04F\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_makefile\": {\n            \"fontCharacter\": \"\\\\E04F\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_markdown_light\": {\n            \"fontCharacter\": \"\\\\E050\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_markdown\": {\n            \"fontCharacter\": \"\\\\E050\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_maven_light\": {\n            \"fontCharacter\": \"\\\\E051\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_maven\": {\n            \"fontCharacter\": \"\\\\E051\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_mdo_light\": {\n            \"fontCharacter\": \"\\\\E052\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_mdo\": {\n            \"fontCharacter\": \"\\\\E052\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_mustache_light\": {\n            \"fontCharacter\": \"\\\\E053\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_mustache\": {\n            \"fontCharacter\": \"\\\\E053\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_new-file\": {\n            \"fontCharacter\": \"\\\\E054\"\n        },\n        \"_npm_light\": {\n            \"fontCharacter\": \"\\\\E055\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_npm\": {\n            \"fontCharacter\": \"\\\\E055\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_npm_ignored_light\": {\n            \"fontCharacter\": \"\\\\E056\",\n            \"fontColor\": \"#3b4b52\"\n        },\n        \"_npm_ignored\": {\n            \"fontCharacter\": \"\\\\E056\",\n            \"fontColor\": \"#41535b\"\n        },\n        \"_nunjucks_light\": {\n            \"fontCharacter\": \"\\\\E057\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_nunjucks\": {\n            \"fontCharacter\": \"\\\\E057\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_ocaml_light\": {\n            \"fontCharacter\": \"\\\\E058\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_ocaml\": {\n            \"fontCharacter\": \"\\\\E058\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_pdf_light\": {\n            \"fontCharacter\": \"\\\\E059\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_pdf\": {\n            \"fontCharacter\": \"\\\\E059\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_perl_light\": {\n            \"fontCharacter\": \"\\\\E05A\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_perl\": {\n            \"fontCharacter\": \"\\\\E05A\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_photoshop_light\": {\n            \"fontCharacter\": \"\\\\E05B\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_photoshop\": {\n            \"fontCharacter\": \"\\\\E05B\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_php_light\": {\n            \"fontCharacter\": \"\\\\E05C\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_php\": {\n            \"fontCharacter\": \"\\\\E05C\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_powershell_light\": {\n            \"fontCharacter\": \"\\\\E05D\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_powershell\": {\n            \"fontCharacter\": \"\\\\E05D\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_project\": {\n            \"fontCharacter\": \"\\\\E05E\"\n        },\n        \"_pug_light\": {\n            \"fontCharacter\": \"\\\\E05F\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_pug\": {\n            \"fontCharacter\": \"\\\\E05F\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_puppet_light\": {\n            \"fontCharacter\": \"\\\\E060\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_puppet\": {\n            \"fontCharacter\": \"\\\\E060\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_python_light\": {\n            \"fontCharacter\": \"\\\\E061\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_python\": {\n            \"fontCharacter\": \"\\\\E061\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_rails\": {\n            \"fontCharacter\": \"\\\\E062\"\n        },\n        \"_react_light\": {\n            \"fontCharacter\": \"\\\\E063\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_react\": {\n            \"fontCharacter\": \"\\\\E063\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_rollup_light\": {\n            \"fontCharacter\": \"\\\\E064\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_rollup\": {\n            \"fontCharacter\": \"\\\\E064\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_ruby_light\": {\n            \"fontCharacter\": \"\\\\E065\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_ruby\": {\n            \"fontCharacter\": \"\\\\E065\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_rust_light\": {\n            \"fontCharacter\": \"\\\\E066\",\n            \"fontColor\": \"#627379\"\n        },\n        \"_rust\": {\n            \"fontCharacter\": \"\\\\E066\",\n            \"fontColor\": \"#6d8086\"\n        },\n        \"_salesforce_light\": {\n            \"fontCharacter\": \"\\\\E067\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_salesforce\": {\n            \"fontCharacter\": \"\\\\E067\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_sass_light\": {\n            \"fontCharacter\": \"\\\\E068\",\n            \"fontColor\": \"#dd4b78\"\n        },\n        \"_sass\": {\n            \"fontCharacter\": \"\\\\E068\",\n            \"fontColor\": \"#f55385\"\n        },\n        \"_sbt_light\": {\n            \"fontCharacter\": \"\\\\E069\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_sbt\": {\n            \"fontCharacter\": \"\\\\E069\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_scala_light\": {\n            \"fontCharacter\": \"\\\\E06A\",\n            \"fontColor\": \"#b8383d\"\n        },\n        \"_scala\": {\n            \"fontCharacter\": \"\\\\E06A\",\n            \"fontColor\": \"#cc3e44\"\n        },\n        \"_search\": {\n            \"fontCharacter\": \"\\\\E06B\"\n        },\n        \"_settings\": {\n            \"fontCharacter\": \"\\\\E06C\"\n        },\n        \"_shell_light\": {\n            \"fontCharacter\": \"\\\\E06D\",\n            \"fontColor\": \"#455155\"\n        },\n        \"_shell\": {\n            \"fontCharacter\": \"\\\\E06D\",\n            \"fontColor\": \"#4d5a5e\"\n        },\n        \"_slim_light\": {\n            \"fontCharacter\": \"\\\\E06E\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_slim\": {\n            \"fontCharacter\": \"\\\\E06E\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_smarty_light\": {\n            \"fontCharacter\": \"\\\\E06F\",\n            \"fontColor\": \"#b7b73b\"\n        },\n        \"_smarty\": {\n            \"fontCharacter\": \"\\\\E06F\",\n            \"fontColor\": \"#cbcb41\"\n        },\n        \"_spring_light\": {\n            \"fontCharacter\": \"\\\\E070\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_spring\": {\n            \"fontCharacter\": \"\\\\E070\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_stylus_light\": {\n            \"fontCharacter\": \"\\\\E071\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_stylus\": {\n            \"fontCharacter\": \"\\\\E071\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_sublime_light\": {\n            \"fontCharacter\": \"\\\\E072\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_sublime\": {\n            \"fontCharacter\": \"\\\\E072\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_svg_light\": {\n            \"fontCharacter\": \"\\\\E073\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_svg\": {\n            \"fontCharacter\": \"\\\\E073\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_swift_light\": {\n            \"fontCharacter\": \"\\\\E074\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_swift\": {\n            \"fontCharacter\": \"\\\\E074\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_terraform_light\": {\n            \"fontCharacter\": \"\\\\E075\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_terraform\": {\n            \"fontCharacter\": \"\\\\E075\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_tex_light\": {\n            \"fontCharacter\": \"\\\\E076\",\n            \"fontColor\": \"#bfc2c1\"\n        },\n        \"_tex\": {\n            \"fontCharacter\": \"\\\\E076\",\n            \"fontColor\": \"#d4d7d6\"\n        },\n        \"_time-cop\": {\n            \"fontCharacter\": \"\\\\E077\"\n        },\n        \"_todo\": {\n            \"fontCharacter\": \"\\\\E078\"\n        },\n        \"_twig_light\": {\n            \"fontCharacter\": \"\\\\E079\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_twig\": {\n            \"fontCharacter\": \"\\\\E079\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_typescript_light\": {\n            \"fontCharacter\": \"\\\\E07A\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_typescript\": {\n            \"fontCharacter\": \"\\\\E07A\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_vala_light\": {\n            \"fontCharacter\": \"\\\\E07B\",\n            \"fontColor\": \"#627379\"\n        },\n        \"_vala\": {\n            \"fontCharacter\": \"\\\\E07B\",\n            \"fontColor\": \"#6d8086\"\n        },\n        \"_video_light\": {\n            \"fontCharacter\": \"\\\\E07C\",\n            \"fontColor\": \"#dd4b78\"\n        },\n        \"_video\": {\n            \"fontCharacter\": \"\\\\E07C\",\n            \"fontColor\": \"#f55385\"\n        },\n        \"_vue_light\": {\n            \"fontCharacter\": \"\\\\E07D\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_vue\": {\n            \"fontCharacter\": \"\\\\E07D\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_windows_light\": {\n            \"fontCharacter\": \"\\\\E07E\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_windows\": {\n            \"fontCharacter\": \"\\\\E07E\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_word_light\": {\n            \"fontCharacter\": \"\\\\E07F\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_word\": {\n            \"fontCharacter\": \"\\\\E07F\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_xls_light\": {\n            \"fontCharacter\": \"\\\\E080\",\n            \"fontColor\": \"#7fae42\"\n        },\n        \"_xls\": {\n            \"fontCharacter\": \"\\\\E080\",\n            \"fontColor\": \"#8dc149\"\n        },\n        \"_xml_light\": {\n            \"fontCharacter\": \"\\\\E081\",\n            \"fontColor\": \"#cc6d2e\"\n        },\n        \"_xml\": {\n            \"fontCharacter\": \"\\\\E081\",\n            \"fontColor\": \"#e37933\"\n        },\n        \"_yarn_light\": {\n            \"fontCharacter\": \"\\\\E082\",\n            \"fontColor\": \"#498ba7\"\n        },\n        \"_yarn\": {\n            \"fontCharacter\": \"\\\\E082\",\n            \"fontColor\": \"#519aba\"\n        },\n        \"_yml_light\": {\n            \"fontCharacter\": \"\\\\E083\",\n            \"fontColor\": \"#9068b0\"\n        },\n        \"_yml\": {\n            \"fontCharacter\": \"\\\\E083\",\n            \"fontColor\": \"#a074c4\"\n        },\n        \"_zip_light\": {\n            \"fontCharacter\": \"\\\\E084\",\n            \"fontColor\": \"#627379\"\n        },\n        \"_zip\": {\n            \"fontCharacter\": \"\\\\E084\",\n            \"fontColor\": \"#6d8086\"\n        }\n    },\n    \"file\": \"_default\",\n    \"fileExtensions\": {\n        \"bsl\": \"_bsl\",\n        \"mdo\": \"_mdo\",\n        \"asm\": \"_asm\",\n        \"s\": \"_asm\",\n        \"h\": \"_c\",\n        \"cfc\": \"_coldfusion\",\n        \"cfm\": \"_coldfusion\",\n        \"config\": \"_config\",\n        \"cfg\": \"_config\",\n        \"conf\": \"_config\",\n        \"cson\": \"_json\",\n        \"css.map\": \"_css\",\n        \"sss\": \"_css\",\n        \"csv\": \"_csv\",\n        \"xls\": \"_xls\",\n        \"xlsx\": \"_xls\",\n        \"cake\": \"_cake\",\n        \"ctp\": \"_cake_php\",\n        \"d\": \"_d\",\n        \"doc\": \"_word\",\n        \"docx\": \"_word\",\n        \"ejs\": \"_ejs\",\n        \"ex\": \"_elixir\",\n        \"exs\": \"_elixir_script\",\n        \"elm\": \"_elm\",\n        \"ico\": \"_favicon\",\n        \"gitignore\": \"_git\",\n        \"gitconfig\": \"_git\",\n        \"gitkeep\": \"_git\",\n        \"gitattributes\": \"_git\",\n        \"gitmodules\": \"_git\",\n        \"slide\": \"_go\",\n        \"article\": \"_go\",\n        \"gradle\": \"_gradle\",\n        \"gsp\": \"_grails\",\n        \"haml\": \"_haml\",\n        \"hjs\": \"_mustache\",\n        \"hs\": \"_haskell\",\n        \"lhs\": \"_haskell\",\n        \"class\": \"_java\",\n        \"classpath\": \"_java\",\n        \"js.map\": \"_javascript\",\n        \"spec.js\": \"_javascript\",\n        \"es\": \"_javascript\",\n        \"es5\": \"_javascript\",\n        \"es7\": \"_javascript\",\n        \"jinja\": \"_jinja\",\n        \"jinja2\": \"_jinja\",\n        \"jl\": \"_julia\",\n        \"js\": \"_javascript\",\n        \"liquid\": \"_liquid\",\n        \"ls\": \"_livescript\",\n        \"md\": \"_markdown\",\n        \"mustache\": \"_mustache\",\n        \"stache\": \"_mustache\",\n        \"njk\": \"_nunjucks\",\n        \"nunjucks\": \"_nunjucks\",\n        \"nunjs\": \"_nunjucks\",\n        \"nunj\": \"_nunjucks\",\n        \"njs\": \"_nunjucks\",\n        \"nj\": \"_nunjucks\",\n        \"npm-debug.log\": \"_npm\",\n        \"npmignore\": \"_npm\",\n        \"npmrc\": \"_npm\",\n        \"ml\": \"_ocaml\",\n        \"mli\": \"_ocaml\",\n        \"cmx\": \"_ocaml\",\n        \"cmxa\": \"_ocaml\",\n        \"php.inc\": \"_php\",\n        \"pug\": \"_pug\",\n        \"pp\": \"_puppet\",\n        \"epp\": \"_puppet\",\n        \"cjsx\": \"_react\",\n        \"erb.html\": \"_ruby\",\n        \"html.erb\": \"_ruby\",\n        \"sass\": \"_sass\",\n        \"springbeans\": \"_spring\",\n        \"slim\": \"_slim\",\n        \"smarty.tpl\": \"_smarty\",\n        \"sbt\": \"_sbt\",\n        \"scala\": \"_scala\",\n        \"styl\": \"_stylus\",\n        \"tf\": \"_terraform\",\n        \"tf.json\": \"_terraform\",\n        \"tex\": \"_tex\",\n        \"sty\": \"_tex\",\n        \"dtx\": \"_tex\",\n        \"ins\": \"_tex\",\n        \"txt\": \"_default\",\n        \"toml\": \"_config\",\n        \"twig\": \"_twig\",\n        \"vala\": \"_vala\",\n        \"vapi\": \"_vala\",\n        \"vue\": \"_vue\",\n        \"jar\": \"_zip\",\n        \"zip\": \"_zip\",\n        \"ai\": \"_illustrator\",\n        \"psd\": \"_photoshop\",\n        \"pdf\": \"_pdf\",\n        \"eot\": \"_font\",\n        \"ttf\": \"_font\",\n        \"woff\": \"_font\",\n        \"woff2\": \"_font\",\n        \"gif\": \"_image\",\n        \"jpg\": \"_image\",\n        \"jpeg\": \"_image\",\n        \"png\": \"_image\",\n        \"pxm\": \"_image\",\n        \"svg\": \"_svg\",\n        \"svgx\": \"_image\",\n        \"webp\": \"_image\",\n        \"sublime-project\": \"_sublime\",\n        \"sublime-workspace\": \"_sublime\",\n        \"component\": \"_salesforce\",\n        \"cls\": \"_salesforce\",\n        \"fish\": \"_shell\",\n        \"mov\": \"_video\",\n        \"ogv\": \"_video\",\n        \"webm\": \"_video\",\n        \"avi\": \"_video\",\n        \"mpg\": \"_video\",\n        \"mp4\": \"_video\",\n        \"mp3\": \"_audio\",\n        \"ogg\": \"_audio\",\n        \"wav\": \"_audio\",\n        \"babelrc\": \"_babel\",\n        \"bowerrc\": \"_bower\",\n        \"dockerignore\": \"_docker\",\n        \"codeclimate.yml\": \"_code-climate\",\n        \"eslintrc\": \"_eslint\",\n        \"eslintrc.js\": \"_eslint\",\n        \"eslintrc.yaml\": \"_eslint\",\n        \"eslintrc.yml\": \"_eslint\",\n        \"eslintrc.json\": \"_eslint\",\n        \"eslintignore\": \"_eslint\",\n        \"firebaserc\": \"_firebase\",\n        \"jshintrc\": \"_javascript\",\n        \"jscsrc\": \"_javascript\",\n        \"direnv\": \"_config\",\n        \"env\": \"_config\",\n        \"static\": \"_config\",\n        \"editorconfig\": \"_config\",\n        \"slugignore\": \"_config\",\n        \"tmp\": \"_clock\",\n        \"htaccess\": \"_config\",\n        \"key\": \"_lock\",\n        \"cert\": \"_lock\",\n        \"ds_store\": \"_ignored\",\n        \"ts\": \"_typescript\",\n        \"tsx\": \"_react\"\n    },\n    \"fileNames\": {\n        \"mix\": \"_hex\",\n        \"karma.conf.js\": \"_karma\",\n        \"karma.conf.coffee\": \"_karma\",\n        \"readme.md\": \"_info\",\n        \"changelog.md\": \"_clock\",\n        \"changelog\": \"_clock\",\n        \"version.md\": \"_clock\",\n        \"version\": \"_clock\",\n        \"mvnw\": \"_maven\",\n        \"mime.types\": \"_config\",\n        \"jenkinsfile\": \"_jenkins\",\n        \"bower.json\": \"_bower\",\n        \"docker-healthcheck\": \"_docker\",\n        \"docker-compose.yml\": \"_docker\",\n        \"firebase.json\": \"_firebase\",\n        \"geckodriver\": \"_firefox\",\n        \"gruntfile.js\": \"_grunt\",\n        \"gruntfile.babel.js\": \"_grunt\",\n        \"gruntfile.coffee\": \"_grunt\",\n        \"gulpfile\": \"_gulp\",\n        \"ionic.config.json\": \"_ionic\",\n        \"ionic.project\": \"_ionic\",\n        \"rollup.config.js\": \"_rollup\",\n        \"sass-lint.yml\": \"_sass\",\n        \"yarn.clean\": \"_yarn\",\n        \"yarn.lock\": \"_yarn\",\n        \"license\": \"_license\",\n        \"licence\": \"_license\",\n        \"copying\": \"_license\",\n        \"compiling\": \"_license\",\n        \"contributing\": \"_license\",\n        \"qmakefile\": \"_makefile\",\n        \"omakefile\": \"_makefile\",\n        \"cmakelists.txt\": \"_makefile\",\n        \"procfile\": \"_heroku\",\n        \"todo\": \"_todo\",\n        \"npm-debug.log\": \"_npm_ignored\"\n    },\n    \"languageIds\": {\n        \"bat\": \"_windows\",\n        \"coffeescript\": \"_coffee\",\n        \"c\": \"_c\",\n        \"cpp\": \"_cpp\",\n        \"csharp\": \"_c-sharp\",\n        \"css\": \"_css\",\n        \"dockerfile\": \"_docker\",\n        \"fsharp\": \"_f-sharp\",\n        \"go\": \"_go2\",\n        \"groovy\": \"_grails\",\n        \"handlebars\": \"_mustache\",\n        \"html\": \"_html\",\n        \"properties\": \"_java\",\n        \"java\": \"_java\",\n        \"javascriptreact\": \"_react\",\n        \"javascript\": \"_javascript\",\n        \"json\": \"_json\",\n        \"less\": \"_less\",\n        \"lua\": \"_lua\",\n        \"makefile\": \"_makefile\",\n        \"markdown\": \"_markdown\",\n        \"objective-c\": \"_c\",\n        \"perl\": \"_perl\",\n        \"php\": \"_php\",\n        \"powershell\": \"_powershell\",\n        \"jade\": \"_jade\",\n        \"python\": \"_python\",\n        \"ruby\": \"_ruby\",\n        \"rust\": \"_rust\",\n        \"scss\": \"_sass\",\n        \"shellscript\": \"_shell\",\n        \"sql\": \"_db\",\n        \"swift\": \"_swift\",\n        \"typescript\": \"_typescript\",\n        \"typescriptreact\": \"_react\",\n        \"xml\": \"_xml\",\n        \"yaml\": \"_yml\"\n    },\n    \"light\": {\n        \"file\": \"_default_light\",\n        \"fileExtensions\": {\n            \"bsl\": \"_bsl_light\",\n            \"mdo\": \"_mdo_light\",\n            \"asm\": \"_asm_light\",\n            \"s\": \"_asm_light\",\n            \"h\": \"_c_light\",\n            \"cfc\": \"_coldfusion_light\",\n            \"cfm\": \"_coldfusion_light\",\n            \"config\": \"_config_light\",\n            \"cfg\": \"_config_light\",\n            \"conf\": \"_config_light\",\n            \"cson\": \"_json_light\",\n            \"css.map\": \"_css_light\",\n            \"sss\": \"_css_light\",\n            \"csv\": \"_csv_light\",\n            \"xls\": \"_xls_light\",\n            \"xlsx\": \"_xls_light\",\n            \"cake\": \"_cake_light\",\n            \"ctp\": \"_cake_php_light\",\n            \"d\": \"_d_light\",\n            \"doc\": \"_word_light\",\n            \"docx\": \"_word_light\",\n            \"ejs\": \"_ejs_light\",\n            \"ex\": \"_elixir_light\",\n            \"exs\": \"_elixir_script_light\",\n            \"elm\": \"_elm_light\",\n            \"ico\": \"_favicon_light\",\n            \"gitignore\": \"_git_light\",\n            \"gitconfig\": \"_git_light\",\n            \"gitkeep\": \"_git_light\",\n            \"gitattributes\": \"_git_light\",\n            \"gitmodules\": \"_git_light\",\n            \"slide\": \"_go_light\",\n            \"article\": \"_go_light\",\n            \"gradle\": \"_gradle_light\",\n            \"gsp\": \"_grails_light\",\n            \"haml\": \"_haml_light\",\n            \"hjs\": \"_mustache_light\",\n            \"hs\": \"_haskell_light\",\n            \"lhs\": \"_haskell_light\",\n            \"class\": \"_java_light\",\n            \"classpath\": \"_java_light\",\n            \"js.map\": \"_javascript_light\",\n            \"spec.js\": \"_javascript_light\",\n            \"es\": \"_javascript_light\",\n            \"es5\": \"_javascript_light\",\n            \"es7\": \"_javascript_light\",\n            \"jinja\": \"_jinja_light\",\n            \"jinja2\": \"_jinja_light\",\n            \"jl\": \"_julia_light\",\n            \"liquid\": \"_liquid_light\",\n            \"ls\": \"_livescript_light\",\n            \"mustache\": \"_mustache_light\",\n            \"stache\": \"_mustache_light\",\n            \"njk\": \"_nunjucks_light\",\n            \"nunjucks\": \"_nunjucks_light\",\n            \"nunjs\": \"_nunjucks_light\",\n            \"nunj\": \"_nunjucks_light\",\n            \"njs\": \"_nunjucks_light\",\n            \"nj\": \"_nunjucks_light\",\n            \"npm-debug.log\": \"_npm_light\",\n            \"npmignore\": \"_npm_light\",\n            \"npmrc\": \"_npm_light\",\n            \"ml\": \"_ocaml_light\",\n            \"mli\": \"_ocaml_light\",\n            \"cmx\": \"_ocaml_light\",\n            \"cmxa\": \"_ocaml_light\",\n            \"php.inc\": \"_php_light\",\n            \"pug\": \"_pug_light\",\n            \"pp\": \"_puppet_light\",\n            \"epp\": \"_puppet_light\",\n            \"cjsx\": \"_react_light\",\n            \"erb.html\": \"_ruby_light\",\n            \"html.erb\": \"_ruby_light\",\n            \"sass\": \"_sass_light\",\n            \"springbeans\": \"_spring_light\",\n            \"slim\": \"_slim_light\",\n            \"smarty.tpl\": \"_smarty_light\",\n            \"sbt\": \"_sbt_light\",\n            \"scala\": \"_scala_light\",\n            \"styl\": \"_stylus_light\",\n            \"tf\": \"_terraform_light\",\n            \"tf.json\": \"_terraform_light\",\n            \"tex\": \"_tex_light\",\n            \"sty\": \"_tex_light\",\n            \"dtx\": \"_tex_light\",\n            \"ins\": \"_tex_light\",\n            \"txt\": \"_default_light\",\n            \"toml\": \"_config_light\",\n            \"twig\": \"_twig_light\",\n            \"vala\": \"_vala_light\",\n            \"vapi\": \"_vala_light\",\n            \"vue\": \"_vue_light\",\n            \"jar\": \"_zip_light\",\n            \"zip\": \"_zip_light\",\n            \"ai\": \"_illustrator_light\",\n            \"psd\": \"_photoshop_light\",\n            \"pdf\": \"_pdf_light\",\n            \"eot\": \"_font_light\",\n            \"ttf\": \"_font_light\",\n            \"woff\": \"_font_light\",\n            \"woff2\": \"_font_light\",\n            \"gif\": \"_image_light\",\n            \"jpg\": \"_image_light\",\n            \"jpeg\": \"_image_light\",\n            \"png\": \"_image_light\",\n            \"pxm\": \"_image_light\",\n            \"svg\": \"_svg_light\",\n            \"svgx\": \"_image_light\",\n            \"sublime-project\": \"_sublime_light\",\n            \"sublime-workspace\": \"_sublime_light\",\n            \"component\": \"_salesforce_light\",\n            \"cls\": \"_salesforce_light\",\n            \"fish\": \"_shell_light\",\n            \"mov\": \"_video_light\",\n            \"ogv\": \"_video_light\",\n            \"webm\": \"_video_light\",\n            \"avi\": \"_video_light\",\n            \"mpg\": \"_video_light\",\n            \"mp4\": \"_video_light\",\n            \"mp3\": \"_audio_light\",\n            \"ogg\": \"_audio_light\",\n            \"wav\": \"_audio_light\",\n            \"babelrc\": \"_babel_light\",\n            \"bowerrc\": \"_bower_light\",\n            \"dockerignore\": \"_docker_light\",\n            \"codeclimate.yml\": \"_code-climate_light\",\n            \"eslintrc\": \"_eslint_light\",\n            \"eslintrc.js\": \"_eslint_light\",\n            \"eslintrc.yaml\": \"_eslint_light\",\n            \"eslintrc.yml\": \"_eslint_light\",\n            \"eslintrc.json\": \"_eslint_light\",\n            \"eslintignore\": \"_eslint_light\",\n            \"firebaserc\": \"_firebase_light\",\n            \"jshintrc\": \"_javascript_light\",\n            \"jscsrc\": \"_javascript_light\",\n            \"direnv\": \"_config_light\",\n            \"env\": \"_config_light\",\n            \"static\": \"_config_light\",\n            \"editorconfig\": \"_config_light\",\n            \"slugignore\": \"_config_light\",\n            \"tmp\": \"_clock_light\",\n            \"htaccess\": \"_config_light\",\n            \"key\": \"_lock_light\",\n            \"cert\": \"_lock_light\",\n            \"ds_store\": \"_ignored_light\"\n        },\n        \"languageIds\": {\n            \"bat\": \"_windows_light\",\n            \"coffeescript\": \"_coffee_light\",\n            \"c\": \"_c_light\",\n            \"cpp\": \"_cpp_light\",\n            \"csharp\": \"_c-sharp_light\",\n            \"css\": \"_css_light\",\n            \"dockerfile\": \"_docker_light\",\n            \"fsharp\": \"_f-sharp_light\",\n            \"go\": \"_go2_light\",\n            \"groovy\": \"_grails_light\",\n            \"handlebars\": \"_mustache_light\",\n            \"html\": \"_html_light\",\n            \"properties\": \"_java_light\",\n            \"java\": \"_java_light\",\n            \"javascriptreact\": \"_react_light\",\n            \"javascript\": \"_javascript_light\",\n            \"json\": \"_json_light\",\n            \"less\": \"_less_light\",\n            \"lua\": \"_lua_light\",\n            \"makefile\": \"_makefile_light\",\n            \"markdown\": \"_markdown_light\",\n            \"objective-c\": \"_c_light\",\n            \"perl\": \"_perl_light\",\n            \"php\": \"_php_light\",\n            \"powershell\": \"_powershell_light\",\n            \"jade\": \"_jade_light\",\n            \"python\": \"_python_light\",\n            \"ruby\": \"_ruby_light\",\n            \"rust\": \"_rust_light\",\n            \"scss\": \"_sass_light\",\n            \"shellscript\": \"_shell_light\",\n            \"sql\": \"_db_light\",\n            \"swift\": \"_swift_light\",\n            \"typescript\": \"_typescript_light\",\n            \"typescriptreact\": \"_react_light\",\n            \"xml\": \"_xml_light\",\n            \"yaml\": \"_yml_light\"\n        },\n        \"fileNames\": {\n            \"mix\": \"_hex_light\",\n            \"karma.conf.js\": \"_karma_light\",\n            \"karma.conf.coffee\": \"_karma_light\",\n            \"readme.md\": \"_info_light\",\n            \"changelog.md\": \"_clock_light\",\n            \"changelog\": \"_clock_light\",\n            \"version.md\": \"_clock_light\",\n            \"version\": \"_clock_light\",\n            \"mvnw\": \"_maven_light\",\n            \"mime.types\": \"_config_light\",\n            \"jenkinsfile\": \"_jenkins_light\",\n            \"bower.json\": \"_bower_light\",\n            \"docker-healthcheck\": \"_docker_light\",\n            \"docker-compose.yml\": \"_docker_light\",\n            \"firebase.json\": \"_firebase_light\",\n            \"geckodriver\": \"_firefox_light\",\n            \"gruntfile.js\": \"_grunt_light\",\n            \"gruntfile.babel.js\": \"_grunt_light\",\n            \"gruntfile.coffee\": \"_grunt_light\",\n            \"gulpfile\": \"_gulp_light\",\n            \"ionic.config.json\": \"_ionic_light\",\n            \"ionic.project\": \"_ionic_light\",\n            \"rollup.config.js\": \"_rollup_light\",\n            \"sass-lint.yml\": \"_sass_light\",\n            \"yarn.clean\": \"_yarn_light\",\n            \"yarn.lock\": \"_yarn_light\",\n            \"license\": \"_license_light\",\n            \"licence\": \"_license_light\",\n            \"copying\": \"_license_light\",\n            \"compiling\": \"_license_light\",\n            \"contributing\": \"_license_light\",\n            \"qmakefile\": \"_makefile_light\",\n            \"omakefile\": \"_makefile_light\",\n            \"cmakelists.txt\": \"_makefile_light\",\n            \"procfile\": \"_heroku_light\",\n            \"npm-debug.log\": \"_npm_ignored_light\"\n        }\n    },\n    \"version\":\n        \"https://github.com/jesseweed/seti-ui/commit/c44b29c7a5b2f189fccfd58ceea02b117678caa9\"\n}\n"
  },
  {
    "path": "extensions/theme-icons-seti/package.json",
    "content": "{\n    \"name\": \"theme-icons-seti\",\n    \"private\": true,\n    \"version\": \"0.0.1\",\n    \"description\": \"A file icon theme made out of the Seti UI file icons\",\n    \"publisher\": \"onivim\",\n    \"engines\": {\n        \"oni\": \"0.2.19\"\n    },\n    \"contributes\": {\n        \"iconThemes\": [\n            {\n                \"id\": \"theme-icons-seti\",\n                \"label\": \"Seti (Oni)\",\n                \"path\": \"./icons/seti-icon-theme.json\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "extensions/theme-icons-seti/thirdpartynotices.txt",
    "content": "﻿\nTHIRD-PARTY SOFTWARE NOTICES AND INFORMATION\nFor Oni theme-icons-seti\n\nThis file is based on or incorporates material from the projects listed below (\"Third Party OSS\"). The original copyright\nnotice and the license under which Oni received such Third Party OSS, are set forth below. \n\n1.       Seti UI - A subtle dark colored UI theme for Atom. (https://github.com/jesseweed/seti-ui)\n\nCopyright (c) 2014 Jesse Weed\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "extensions/theme-nord/README.md",
    "content": "Adaption of the nord theme from articicestudio:\nhttps://github.com/arcticicestudio/nord-vim/blob/develop/colors/nord.vim\n"
  },
  {
    "path": "extensions/theme-nord/colors/nord.json",
    "content": "{\n    \"name\": \"nord\",\n    \"baseVimTheme\": \"nord\",\n    \"colors\": {\n        \"background\": \"#212733\",\n        \"foreground\": \"#ECEFF4\",\n\n        \"title.background\": \"#212733\",\n        \"title.foreground\": \"#ECEFF4\",\n\n        \"editor.background\": \"#2F3440\",\n        \"editor.foreground\": \"#DCDCDC\",\n\n        \"tabs.background\": \"#2F3440\",\n        \"tabs.foreground\": \"#E5E9F0\",\n\n        \"toolTip.background\": \"#2E3440\",\n        \"toolTip.foreground\": \"#E5E9F0\",\n        \"toolTip.border\": \"#505050\",\n\n        \"menu.background\": \"#2E3440\",\n        \"menu.foreground\": \"#E5E9F0\",\n        \"menu.border\": \"#505050\",\n\n        \"contextMenu.background\": \"#3B4252\",\n        \"contextMenu.foreground\": \"#ABB2BF\",\n        \"contextMenu.border\": \"#505050\",\n        \"contextMenu.highlight\": \"#3F4652\",\n\n        \"sidebar.background\": \"#3B4252\",\n        \"sidebar.foreground\": \"#ABB2BF\",\n        \"sidebar.active.background\": \"#282C34\",\n        \"sidebar.selection.border\": \"#61afef\",\n\n        \"statusBar.background\": \"#282828\",\n        \"statusBar.foreground\": \"#c8c8c8\",\n\n        \"highlight.mode.insert.background\": \"#98c379\",\n        \"highlight.mode.insert.foreground\": \"#282c34\",\n\n        \"highlight.mode.normal.background\": \"#61afef\",\n        \"highlight.mode.normal.foreground\": \"#282c34\",\n\n        \"highlight.mode.operator.background\": \"#d19a66\",\n        \"highlight.mode.operator.foreground\": \"#282c34\",\n\n        \"highlight.mode.visual.background\": \"#56b6c2\",\n        \"highlight.mode.visual.foreground\": \"#282c34\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-nord/colors/nord.vim",
    "content": "\" Copyright (c) 2016-2017 Arctic Ice Studio <development@arcticicestudio.com>\n\" Copyright (c) 2016-2017 Sven Greb <code@svengreb.de>\n\n\" Project: Nord Vim\n\" Repository: https://github.com/arcticicestudio/nord-vim\n\" License: MIT\n\nif version > 580\n  hi clear\n  if exists(\"syntax_on\")\n    syntax reset\n  endif\nendif\n\nlet g:colors_name = \"nord\"\nlet s:nord_vim_version=\"0.6.0\"\nset background=dark\n\nlet s:nord0_gui = \"#2E3440\"\nlet s:nord1_gui = \"#3B4252\"\nlet s:nord2_gui = \"#434C5E\"\nlet s:nord3_gui = \"#4C566A\"\nlet s:nord4_gui = \"#D8DEE9\"\nlet s:nord5_gui = \"#E5E9F0\"\nlet s:nord6_gui = \"#ECEFF4\"\nlet s:nord7_gui = \"#8FBCBB\"\nlet s:nord8_gui = \"#88C0D0\"\nlet s:nord9_gui = \"#81A1C1\"\nlet s:nord10_gui = \"#5E81AC\"\nlet s:nord11_gui = \"#BF616A\"\nlet s:nord12_gui = \"#D08770\"\nlet s:nord13_gui = \"#EBCB8B\"\nlet s:nord14_gui = \"#A3BE8C\"\nlet s:nord15_gui = \"#B48EAD\"\n\nlet s:nord1_term = \"0\"\nlet s:nord3_term = \"8\"\nlet s:nord5_term = \"7\"\nlet s:nord6_term = \"15\"\nlet s:nord7_term = \"14\"\nlet s:nord8_term = \"6\"\nlet s:nord9_term = \"4\"\nlet s:nord10_term = \"12\"\nlet s:nord11_term = \"1\"\nlet s:nord12_term = \"11\"\nlet s:nord13_term = \"3\"\nlet s:nord14_term = \"2\"\nlet s:nord15_term = \"5\"\n\nlet s:nord3_gui_brightened = [\n  \\ s:nord3_gui,\n  \\ \"#4e586d\",\n  \\ \"#505b70\",\n  \\ \"#525d73\",\n  \\ \"#556076\",\n  \\ \"#576279\",\n  \\ \"#59647c\",\n  \\ \"#5b677f\",\n  \\ \"#5d6982\",\n  \\ \"#5f6c85\",\n  \\ \"#616e88\",\n  \\ \"#63718b\",\n  \\ \"#66738e\",\n  \\ \"#687591\",\n  \\ \"#6a7894\",\n  \\ \"#6d7a96\",\n  \\ \"#6f7d98\",\n  \\ \"#72809a\",\n  \\ \"#75829c\",\n  \\ \"#78859e\",\n  \\ \"#7b88a1\",\n\\ ]\n\nif !exists(\"g:nord_italic_comments\")\n  let g:nord_italic_comments = 0\nendif\n\nif !exists('g:nord_uniform_status_lines')\n  let g:nord_uniform_status_lines = 0\nendif\n\nif !exists(\"g:nord_comment_brightness\")\n  let g:nord_comment_brightness = 0\nendif\n\nif !exists(\"g:nord_uniform_diff_background\")\n  let g:nord_uniform_diff_background = 0\nendif\n\nfunction! s:hi(group, guifg, guibg, ctermfg, ctermbg, attr, guisp)\n  let l:attr = a:attr\n  if g:nord_italic_comments == 0 && l:attr ==? 'italic'\n    let l:attr= 'NONE'\n  endif\n\n  if a:guifg != \"\"\n    exec \"hi \" . a:group . \" guifg=\" . a:guifg\n  endif\n  if a:guibg != \"\"\n    exec \"hi \" . a:group . \" guibg=\" . a:guibg\n  endif\n  if a:ctermfg != \"\"\n    exec \"hi \" . a:group . \" ctermfg=\" . a:ctermfg\n  endif\n  if a:ctermbg != \"\"\n    exec \"hi \" . a:group . \" ctermbg=\" . a:ctermbg\n  endif\n  if a:attr != \"\"\n    exec \"hi \" . a:group . \" gui=\" . l:attr . \" cterm=\" . l:attr\n  endif\n  if a:guisp != \"\"\n    exec \"hi \" . a:group . \" guisp=\" . a:guisp\n  endif\nendfunction\n\n\"+---------------+\n\"+ UI Components +\n\"+---------------+\n\"+--- Attributes ---+\ncall s:hi(\"Bold\", \"\", \"\", \"\", \"\", \"bold\", \"\")\ncall s:hi(\"Italic\", \"\", \"\", \"\", \"\", \"italic\", \"\")\ncall s:hi(\"Underline\", \"\", \"\", \"\", \"\", \"underline\", \"\")\n\n\"+--- Editor ---+\ncall s:hi(\"ColorColumn\", \"\", s:nord1_gui, \"NONE\", s:nord1_term, \"\", \"\")\ncall s:hi(\"Cursor\", s:nord0_gui, s:nord4_gui, \"\", \"NONE\", \"\", \"\")\ncall s:hi(\"CursorLine\", \"\", s:nord1_gui, \"NONE\", s:nord1_term, \"NONE\", \"\")\ncall s:hi(\"Error\", s:nord0_gui, s:nord11_gui, \"\", s:nord11_term, \"\", \"\")\ncall s:hi(\"iCursor\", s:nord0_gui, s:nord4_gui, \"\", \"NONE\", \"\", \"\")\ncall s:hi(\"LineNr\", s:nord3_gui, s:nord0_gui, s:nord3_term, \"NONE\", \"\", \"\")\ncall s:hi(\"MatchParen\", s:nord0_gui, s:nord8_gui, s:nord1_term, s:nord8_term, \"\", \"\")\ncall s:hi(\"NonText\", s:nord2_gui, \"\", s:nord3_term, \"\", \"\", \"\")\ncall s:hi(\"Normal\", s:nord4_gui, s:nord0_gui, \"NONE\", \"NONE\", \"\", \"\")\ncall s:hi(\"PMenu\", s:nord4_gui, s:nord2_gui, \"NONE\", s:nord1_term, \"NONE\", \"\")\ncall s:hi(\"PmenuSbar\", s:nord4_gui, s:nord2_gui, \"NONE\", s:nord1_term, \"\", \"\")\ncall s:hi(\"PMenuSel\", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, \"\", \"\")\ncall s:hi(\"PmenuThumb\", s:nord8_gui, s:nord3_gui, \"NONE\", s:nord3_term, \"\", \"\")\ncall s:hi(\"SpecialKey\", s:nord3_gui, \"\", s:nord3_term, \"\", \"\", \"\")\ncall s:hi(\"SpellBad\", \"\", s:nord0_gui, \"\", \"NONE\", \"undercurl\", s:nord11_gui)\ncall s:hi(\"SpellCap\", \"\", s:nord0_gui, \"\", \"NONE\", \"undercurl\", s:nord13_gui)\ncall s:hi(\"SpellLocal\", \"\", s:nord0_gui, \"\", \"NONE\", \"undercurl\", s:nord5_gui)\ncall s:hi(\"SpellRare\", \"\", s:nord0_gui, \"\", \"NONE\", \"undercurl\", s:nord6_gui)\ncall s:hi(\"Visual\", \"\", s:nord2_gui, \"\", s:nord1_term, \"\", \"\")\ncall s:hi(\"VisualNOS\", \"\", s:nord2_gui, \"\", s:nord1_term, \"\", \"\")\n\"+- Neovim Support -+\ncall s:hi(\"healthError\", s:nord11_gui, s:nord1_gui, s:nord11_term, s:nord1_term, \"\", \"\")\ncall s:hi(\"healthSuccess\", s:nord14_gui, s:nord1_gui, s:nord14_term, s:nord1_term, \"\", \"\")\ncall s:hi(\"healthWarning\", s:nord13_gui, s:nord1_gui, s:nord13_term, s:nord1_term, \"\", \"\")\n\n\"+- Neovim Terminal Colors -+\nif has('nvim')\n  let g:terminal_color_0 = s:nord1_gui\n  let g:terminal_color_1 = s:nord11_gui\n  let g:terminal_color_2 = s:nord14_gui\n  let g:terminal_color_3 = s:nord13_gui\n  let g:terminal_color_4 = s:nord9_gui\n  let g:terminal_color_5 = s:nord15_gui\n  let g:terminal_color_6 = s:nord8_gui\n  let g:terminal_color_7 = s:nord5_gui\n  let g:terminal_color_8 = s:nord3_gui\n  let g:terminal_color_9 = s:nord11_gui\n  let g:terminal_color_10 = s:nord14_gui\n  let g:terminal_color_11 = s:nord13_gui\n  let g:terminal_color_12 = s:nord9_gui\n  let g:terminal_color_13 = s:nord15_gui\n  let g:terminal_color_14 = s:nord7_gui\n  let g:terminal_color_15 = s:nord6_gui\nendif\n\n\"+--- Gutter ---+\ncall s:hi(\"CursorColumn\", \"\", s:nord1_gui, \"NONE\", s:nord1_term, \"\", \"\")\ncall s:hi(\"CursorLineNr\", s:nord3_gui, s:nord0_gui, \"NONE\", \"\", \"\", \"\")\ncall s:hi(\"Folded\", s:nord3_gui, s:nord1_gui, s:nord3_term, s:nord1_term, \"bold\", \"\")\ncall s:hi(\"FoldColumn\", s:nord3_gui, s:nord0_gui, s:nord3_term, \"NONE\", \"\", \"\")\ncall s:hi(\"SignColumn\", s:nord1_gui, s:nord0_gui, s:nord1_term, \"NONE\", \"\", \"\")\n\n\"+--- Navigation ---+\ncall s:hi(\"Directory\", s:nord8_gui, \"\", s:nord8_term, \"NONE\", \"\", \"\")\n\n\"+--- Prompt/Status ---+\ncall s:hi(\"EndOfBuffer\", s:nord1_gui, \"\", s:nord1_term, \"NONE\", \"\", \"\")\ncall s:hi(\"ErrorMsg\", s:nord4_gui, s:nord11_gui, \"NONE\", s:nord11_term, \"\", \"\")\ncall s:hi(\"ModeMsg\", s:nord4_gui, \"\", \"\", \"\", \"\", \"\")\ncall s:hi(\"MoreMsg\", s:nord4_gui, \"\", \"\", \"\", \"\", \"\")\ncall s:hi(\"Question\", s:nord4_gui, \"\", \"NONE\", \"\", \"\", \"\")\nif g:nord_uniform_status_lines == 0\n  call s:hi(\"StatusLine\", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, \"NONE\", \"\")\n  call s:hi(\"StatusLineNC\", s:nord4_gui, s:nord1_gui, \"NONE\", s:nord1_term, \"NONE\", \"\")\nelse\n  call s:hi(\"StatusLine\", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, \"NONE\", \"\")\n  call s:hi(\"StatusLineNC\", s:nord4_gui, s:nord3_gui, \"NONE\", s:nord3_term, \"NONE\", \"\")\nendif\ncall s:hi(\"WarningMsg\", s:nord0_gui, s:nord13_gui, s:nord1_term, s:nord13_term, \"\", \"\")\ncall s:hi(\"WildMenu\", s:nord8_gui, s:nord1_gui, s:nord8_term, s:nord1_term, \"\", \"\")\n\n\"+--- Search ---+\ncall s:hi(\"IncSearch\", s:nord1_gui, s:nord8_gui, s:nord1_term, s:nord8_term, \"underline\", \"\")\ncall s:hi(\"Search\", s:nord1_gui, s:nord8_gui, s:nord1_term, s:nord8_term, \"NONE\", \"\")\n\n\"+--- Tabs ---+\ncall s:hi(\"TabLine\", s:nord4_gui, s:nord1_gui, \"NONE\", s:nord1_term, \"NONE\", \"\")\ncall s:hi(\"TabLineFill\", s:nord4_gui, s:nord1_gui, \"NONE\", s:nord1_term, \"NONE\", \"\")\ncall s:hi(\"TabLineSel\", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, \"NONE\", \"\")\n\n\"+--- Window ---+\ncall s:hi(\"Title\", s:nord4_gui, \"\", \"NONE\", \"\", \"NONE\", \"\")\ncall s:hi(\"VertSplit\", s:nord2_gui, s:nord1_gui, s:nord3_term, s:nord1_term, \"NONE\", \"\")\n\n\"+----------------------+\n\"+ Language Base Groups +\n\"+----------------------+\ncall s:hi(\"Boolean\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Character\", s:nord14_gui, \"\", s:nord14_term, \"\", \"\", \"\")\ncall s:hi(\"Comment\", s:nord3_gui_brightened[g:nord_comment_brightness], \"\", s:nord3_term, \"\", \"italic\", \"\")\ncall s:hi(\"Conditional\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Constant\", s:nord4_gui, \"\", \"NONE\", \"\", \"\", \"\")\ncall s:hi(\"Define\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Delimiter\", s:nord6_gui, \"\", s:nord6_term, \"\", \"\", \"\")\ncall s:hi(\"Exception\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Float\", s:nord15_gui, \"\", s:nord15_term, \"\", \"\", \"\")\ncall s:hi(\"Function\", s:nord8_gui, \"\", s:nord8_term, \"\", \"\", \"\")\ncall s:hi(\"Identifier\", s:nord4_gui, \"\", \"NONE\", \"\", \"NONE\", \"\")\ncall s:hi(\"Include\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Keyword\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Label\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Number\", s:nord15_gui, \"\", s:nord15_term, \"\", \"\", \"\")\ncall s:hi(\"Operator\", s:nord9_gui, \"\", s:nord9_term, \"\", \"NONE\", \"\")\ncall s:hi(\"PreProc\", s:nord9_gui, \"\", s:nord9_term, \"\", \"NONE\", \"\")\ncall s:hi(\"Repeat\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Special\", s:nord4_gui, \"\", \"NONE\", \"\", \"\", \"\")\ncall s:hi(\"SpecialChar\", s:nord13_gui, \"\", s:nord13_term, \"\", \"\", \"\")\ncall s:hi(\"SpecialComment\", s:nord8_gui, \"\", s:nord8_term, \"\", \"italic\", \"\")\ncall s:hi(\"Statement\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"StorageClass\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"String\", s:nord14_gui, \"\", s:nord14_term, \"\", \"\", \"\")\ncall s:hi(\"Structure\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\ncall s:hi(\"Tag\", s:nord4_gui, \"\", \"\", \"\", \"\", \"\")\ncall s:hi(\"Todo\", s:nord13_gui, \"NONE\", s:nord13_term, \"NONE\", \"\", \"\")\ncall s:hi(\"Type\", s:nord9_gui, \"\", s:nord9_term, \"\", \"NONE\", \"\")\ncall s:hi(\"Typedef\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\nhi! link Macro Define\nhi! link PreCondit PreProc\n\n\"+-----------+\n\"+ Languages +\n\"+-----------+\ncall s:hi(\"awkCharClass\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"awkPatterns\", s:nord9_gui, \"\", s:nord9_term, \"\", \"bold\", \"\")\nhi! link awkArrayElement Identifier\nhi! link awkBoolLogic Keyword\nhi! link awkBrktRegExp SpecialChar\nhi! link awkComma Delimiter\nhi! link awkExpression Keyword\nhi! link awkFieldVars Identifier\nhi! link awkLineSkip Keyword\nhi! link awkOperator Operator\nhi! link awkRegExp SpecialChar\nhi! link awkSearch Keyword\nhi! link awkSemicolon Delimiter\nhi! link awkSpecialCharacter SpecialChar\nhi! link awkSpecialPrintf SpecialChar\nhi! link awkVariables Identifier\n\ncall s:hi(\"cIncluded\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link cOperator Operator\nhi! link cPreCondit PreCondit\n\nhi! link csPreCondit PreCondit\nhi! link csType Type\nhi! link csXmlTag SpecialComment\n\ncall s:hi(\"cssAttributeSelector\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"cssDefinition\", s:nord7_gui, \"\", s:nord7_term, \"\", \"NONE\", \"\")\ncall s:hi(\"cssIdentifier\", s:nord7_gui, \"\", s:nord7_term, \"\", \"underline\", \"\")\ncall s:hi(\"cssStringQ\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link cssAttr Keyword\nhi! link cssBraces Delimiter\nhi! link cssClassName cssDefinition\nhi! link cssColor Number\nhi! link cssProp cssDefinition\nhi! link cssPseudoClass cssDefinition\nhi! link cssPseudoClassId cssPseudoClass\nhi! link cssVendor Keyword\n\ncall s:hi(\"dosiniHeader\", s:nord8_gui, \"\", s:nord8_term, \"\", \"\", \"\")\nhi! link dosiniLabel Type\n\ncall s:hi(\"dtBooleanKey\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"dtExecKey\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"dtLocaleKey\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"dtNumericKey\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"dtTypeKey\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link dtDelim Delimiter\nhi! link dtLocaleValue Keyword\nhi! link dtTypeValue Keyword\n\nif g:nord_uniform_diff_background == 0\n  call s:hi(\"DiffAdd\", s:nord14_gui, s:nord0_gui, s:nord14_term, \"NONE\", \"inverse\", \"\")\n  call s:hi(\"DiffChange\", s:nord13_gui, s:nord0_gui, s:nord13_term, \"NONE\", \"inverse\", \"\")\n  call s:hi(\"DiffDelete\", s:nord11_gui, s:nord0_gui, s:nord11_term, \"NONE\", \"inverse\", \"\")\n  call s:hi(\"DiffText\", s:nord13_gui, s:nord0_gui, s:nord13_term, \"NONE\", \"inverse\", \"\")\nelse\n  call s:hi(\"DiffAdd\", s:nord14_gui, s:nord1_gui, s:nord14_term, s:nord1_term, \"\", \"\")\n  call s:hi(\"DiffChange\", s:nord13_gui, s:nord1_gui, s:nord13_term, s:nord1_term, \"\", \"\")\n  call s:hi(\"DiffDelete\", s:nord11_gui, s:nord1_gui, s:nord11_term, s:nord1_term, \"\", \"\")\n  call s:hi(\"DiffText\", s:nord13_gui, s:nord1_gui, s:nord13_term, s:nord1_term, \"\", \"\")\nendif\n\" Legacy groups for official git.vim and diff.vim syntax\nhi! link diffAdded DiffAdd\nhi! link diffChanged DiffChange\nhi! link diffRemoved DiffDelete\n\ncall s:hi(\"gitconfigVariable\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\n\ncall s:hi(\"goBuiltins\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link goConstants Keyword\n\ncall s:hi(\"htmlArg\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"htmlLink\", s:nord4_gui, \"\", \"\", \"\", \"NONE\", \"NONE\")\nhi! link htmlBold Bold\nhi! link htmlEndTag htmlTag\nhi! link htmlItalic Italic\nhi! link htmlH1 markdownH1\nhi! link htmlH2 markdownH1\nhi! link htmlH3 markdownH1\nhi! link htmlH4 markdownH1\nhi! link htmlH5 markdownH1\nhi! link htmlH6 markdownH1\nhi! link htmlSpecialChar SpecialChar\nhi! link htmlTag Keyword\nhi! link htmlTagN htmlTag\n\ncall s:hi(\"javaDocTags\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link javaCommentTitle Comment\nhi! link javaScriptBraces Delimiter\nhi! link javaScriptIdentifier Keyword\nhi! link javaScriptNumber Number\n\ncall s:hi(\"jsonKeyword\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\n\ncall s:hi(\"lessClass\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link lessAmpersand Keyword\nhi! link lessCssAttribute Delimiter\nhi! link lessFunction Function\nhi! link cssSelectorOp Keyword\n\nhi! link lispAtomBarSymbol SpecialChar\nhi! link lispAtomList SpecialChar\nhi! link lispAtomMark Keyword\nhi! link lispBarSymbol SpecialChar\nhi! link lispFunc Function\n\nhi! link luaFunc Function\n\ncall s:hi(\"markdownBlockquote\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"markdownCode\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"markdownCodeDelimiter\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"markdownFootnote\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"markdownId\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"markdownIdDeclaration\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"markdownH1\", s:nord8_gui, \"\", s:nord8_term, \"\", \"\", \"\")\ncall s:hi(\"markdownLinkText\", s:nord8_gui, \"\", s:nord8_term, \"\", \"\", \"\")\ncall s:hi(\"markdownUrl\", s:nord4_gui, \"\", \"NONE\", \"\", \"NONE\", \"\")\nhi! link markdownFootnoteDefinition markdownFootnote\nhi! link markdownH2 markdownH1\nhi! link markdownH3 markdownH1\nhi! link markdownH4 markdownH1\nhi! link markdownH5 markdownH1\nhi! link markdownH6 markdownH1\nhi! link markdownIdDelimiter Keyword\nhi! link markdownLinkDelimiter Keyword\nhi! link markdownLinkTextDelimiter Keyword\nhi! link markdownListMarker Keyword\nhi! link markdownRule Keyword\nhi! link markdownHeadingDelimiter Keyword\n\ncall s:hi(\"perlPackageDecl\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\n\ncall s:hi(\"phpClasses\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"phpDocTags\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link phpDocCustomTags phpDocTags\nhi! link phpMemberSelector Keyword\n\ncall s:hi(\"podCmdText\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"podVerbatimLine\", s:nord4_gui, \"\", \"NONE\", \"\", \"\", \"\")\nhi! link podFormat Keyword\n\nhi! link pythonBuiltin Type\nhi! link pythonEscape SpecialChar\n\ncall s:hi(\"rubyConstant\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"rubySymbol\", s:nord6_gui, \"\", s:nord6_term, \"\", \"bold\", \"\")\nhi! link rubyAttribute Identifier\nhi! link rubyBlockParameterList Operator\nhi! link rubyInterpolationDelimiter Keyword\nhi! link rubyKeywordAsMethod Function\nhi! link rubyLocalVariableOrMethod Function\nhi! link rubyPseudoVariable Keyword\nhi! link rubyRegexp SpecialChar\n\ncall s:hi(\"sassClass\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"sassId\", s:nord7_gui, \"\", s:nord7_term, \"\", \"underline\", \"\")\nhi! link sassAmpersand Keyword\nhi! link sassClassChar Delimiter\nhi! link sassControl Keyword\nhi! link sassControlLine Keyword\nhi! link sassExtend Keyword\nhi! link sassFor Keyword\nhi! link sassFunctionDecl Keyword\nhi! link sassFunctionName Function\nhi! link sassidChar sassId\nhi! link sassInclude SpecialChar\nhi! link sassMixinName Function\nhi! link sassMixing SpecialChar\nhi! link sassReturn Keyword\n\nhi! link shCmdParenRegion Delimiter\nhi! link shCmdSubRegion Delimiter\nhi! link shDerefSimple Identifier\nhi! link shDerefVar Identifier\n\nhi! link sqlKeyword Keyword\nhi! link sqlSpecial Keyword\n\ncall s:hi(\"vimAugroup\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"vimMapRhs\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"vimNotation\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link vimFunc Function\nhi! link vimFunction Function\nhi! link vimUserFunc Function\n\ncall s:hi(\"xmlAttrib\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"xmlCdataStart\", s:nord3_gui, \"\", s:nord3_term, \"\", \"bold\", \"\")\ncall s:hi(\"xmlNamespace\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link xmlAttribPunct Delimiter\nhi! link xmlCdata Comment\nhi! link xmlCdataCdata xmlCdataStart\nhi! link xmlCdataEnd xmlCdataStart\nhi! link xmlEndTag xmlTagName\nhi! link xmlProcessingDelim Keyword\nhi! link xmlTagName Keyword\n\ncall s:hi(\"yamlBlockMappingKey\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link yamlBool Keyword\nhi! link yamlDocumentStart Keyword\n\n\"+----------------+\n\"+ Plugin Support +\n\"+----------------+\n\"+--- UI ---+\n\" ALE\n\" > w0rp/ale\ncall s:hi(\"ALEWarningSign\", s:nord13_gui, \"\", s:nord13_term, \"\", \"\", \"\")\ncall s:hi(\"ALEErrorSign\" , s:nord11_gui, \"\", s:nord11_term, \"\", \"\", \"\")\n\n\" GitGutter\n\" > airblade/vim-gitgutter\ncall s:hi(\"GitGutterAdd\", s:nord14_gui, \"\", s:nord14_term, \"\", \"\", \"\")\ncall s:hi(\"GitGutterChange\", s:nord13_gui, \"\", s:nord13_term, \"\", \"\", \"\")\ncall s:hi(\"GitGutterChangeDelete\", s:nord11_gui, \"\", s:nord11_term, \"\", \"\", \"\")\ncall s:hi(\"GitGutterDelete\", s:nord11_gui, \"\", s:nord11_term, \"\", \"\", \"\")\n\n\" fugitive.vim\n\" > tpope/vim-fugitive\ncall s:hi(\"gitcommitDiscardedFile\", s:nord11_gui, \"\", s:nord11_term, \"\", \"\", \"\")\ncall s:hi(\"gitcommitUntrackedFile\", s:nord11_gui, \"\", s:nord11_term, \"\", \"\", \"\")\ncall s:hi(\"gitcommitSelectedFile\", s:nord14_gui, \"\", s:nord14_term, \"\", \"\", \"\")\n\n\" davidhalter/jedi-vim\ncall s:hi(\"jediFunction\", s:nord4_gui, s:nord3_gui, \"\", s:nord3_term, \"\", \"\")\ncall s:hi(\"jediFat\", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, \"bold,underline\", \"\")\n\n\" NERDTree\n\" > scrooloose/nerdtree\ncall s:hi(\"NERDTreeExecFile\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\nhi! link NERDTreeDirSlash Keyword\nhi! link NERDTreeHelp Comment\n\n\" CtrlP\n\" > ctrlpvim/ctrlp.vim\nhi! link CtrlPMatch Keyword\nhi! link CtrlPBufferHid Normal\n\n\" vim-plug\n\" > junegunn/vim-plug\ncall s:hi(\"plugDeleted\", s:nord11_gui, \"\", \"\", s:nord11_term, \"\", \"\")\n\n\"+--- Languages ---+\n\" JavaScript\n\" > pangloss/vim-javascript\ncall s:hi(\"jsGlobalNodeObjects\", s:nord8_gui, \"\", s:nord8_term, \"\", \"italic\", \"\")\nhi! link jsBrackets Delimiter\nhi! link jsFuncCall Function\nhi! link jsFuncParens Delimiter\nhi! link jsNoise Delimiter\nhi! link jsPrototype Keyword\nhi! link jsRegexpString SpecialChar\n\n\" Markdown\n\" > plasticboy/vim-markdown\ncall s:hi(\"mkdCode\", s:nord7_gui, \"\", s:nord7_term, \"\", \"\", \"\")\ncall s:hi(\"mkdFootnote\", s:nord8_gui, \"\", s:nord8_term, \"\", \"\", \"\")\ncall s:hi(\"mkdRule\", s:nord10_gui, \"\", s:nord10_term, \"\", \"\", \"\")\ncall s:hi(\"mkdLineBreak\", s:nord9_gui, \"\", s:nord9_term, \"\", \"\", \"\")\nhi! link mkdBold Bold\nhi! link mkdItalic Italic\nhi! link mkdString Keyword\nhi! link mkdCodeStart mkdCode\nhi! link mkdCodeEnd mkdCode\nhi! link mkdBlockquote Comment\nhi! link mkdListItem Keyword\nhi! link mkdListItemLine Normal\nhi! link mkdFootnotes mkdFootnote\nhi! link mkdLink markdownLinkText\nhi! link mkdURL markdownUrl\nhi! link mkdInlineURL mkdURL\nhi! link mkdID Identifier \"CHECK\nhi! link mkdLinkDef mkdLink\nhi! link mkdLinkDefTarget mkdURL\nhi! link mkdLinkTitle mkdInlineURL\nhi! link mkdDelimiter Keyword\n"
  },
  {
    "path": "extensions/theme-nord/package.json",
    "content": "{\n    \"name\": \"theme-nord\",\n    \"version\": \"0.0.1\",\n    \"description\": \"Nord theme, customized for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"themes\": [\n            {\n                \"name\": \"nord\",\n                \"path\": \"colors/nord.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/theme-onedark/colors/onedark.json",
    "content": "{\n    \"name\": \"onedark\",\n    \"baseVimTheme\": \"onedark\",\n    \"colors\": {\n        \"background\": \"#1E2127\",\n        \"foreground\": \"#ABB2BF\",\n\n        \"title.background\": \"#1E2127\",\n        \"title.foreground\": \"#ABB2BF\",\n\n        \"editor.background\": \"#282C34\",\n        \"editor.foreground\": \"#ABB2BF\",\n\n        \"tabs.background\": \"#282C34\",\n        \"tabs.foreground\": \"#ABB3BF\",\n\n        \"toolTip.background\": \"#282C34\",\n        \"toolTip.foreground\": \"#ABB2BF\",\n        \"toolTip.border\": \"#505050\",\n\n        \"menu.background\": \"#282C34\",\n        \"menu.foreground\": \"#ABB2BF\",\n        \"menu.border\": \"#505050\",\n\n        \"contextMenu.background\": \"#282C34\",\n        \"contextMenu.foreground\": \"#ABB2BF\",\n        \"contextMenu.border\": \"#505050\",\n        \"contextMenu.highlight\": \"#3F4652\",\n\n        \"sidebar.background\": \"#1E2127\",\n        \"sidebar.foreground\": \"#ABB2BF\",\n        \"sidebar.active.background\": \"#282C34\",\n        \"sidebar.selection.border\": \"#61afef\",\n\n        \"statusBar.background\": \"#282828\",\n        \"statusBar.foreground\": \"#c8c8c8\",\n\n        \"highlight.mode.insert.background\": \"#98c379\",\n        \"highlight.mode.insert.foreground\": \"#282c34\",\n\n        \"highlight.mode.normal.background\": \"#61afef\",\n        \"highlight.mode.normal.foreground\": \"#282c34\",\n\n        \"highlight.mode.operator.background\": \"#d19a66\",\n        \"highlight.mode.operator.foreground\": \"#282c34\",\n\n        \"highlight.mode.visual.background\": \"#56b6c2\",\n        \"highlight.mode.visual.foreground\": \"#282c34\",\n        \"editor.tokenColors\": [\n            {\n                \"settings\": {\n                    \"background\": \"#282c34\",\n                    \"foreground\": \"#abb2bf\",\n                    \"findHighlight\": \"#FFE792\",\n                    \"findHighlightForeground\": \"#000000\",\n                    \"selectionBorder\": \"#222218\",\n                    \"activeGuide\": \"#9D550FB0\",\n                    \"bracketsForeground\": \"#F8F8F2A5\",\n                    \"bracketsOptions\": \"underline\",\n                    \"bracketContentsForeground\": \"#F8F8F2A5\",\n                    \"bracketContentsOptions\": \"underline\",\n                    \"tagsOptions\": \"stippled_underline\"\n                }\n            },\n            {\n                \"name\": \"Comment\",\n                \"scope\": \"comment\",\n                \"settings\": {\n                    \"foreground\": \"#5c6370\",\n                    \"fontStyle\": \"italic\"\n                }\n            },\n            {\n                \"name\": \"Comment\",\n                \"scope\": \"html.doctype\",\n                \"settings\": {\n                    \"foreground\": \"#5c6370\",\n                    \"fontStyle\": \"italic\"\n                }\n            },\n            {\n                \"name\": \"String\",\n                \"scope\": \"string\",\n                \"settings\": {\n                    \"foreground\": \"#98c379\"\n                }\n            },\n            {\n                \"name\": \"Embeded String Begin and End\",\n                \"scope\": [\"string.embedded.begin\", \"string.embedded.end\"],\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Embeded String\",\n                \"scope\": \"string.embedded\",\n                \"settings\": {\n                    \"foreground\": \"#56b6c2\"\n                }\n            },\n            {\n                \"name\": \"Number\",\n                \"scope\": \"constant.numeric\",\n                \"settings\": {\n                    \"foreground\": \"#d19a66\"\n                }\n            },\n            {\n                \"name\": \"Built-in constant\",\n                \"scope\": \"constant.language\",\n                \"settings\": {\n                    \"foreground\": \"#d19a66\"\n                }\n            },\n            {\n                \"name\": \"User-defined constant\",\n                \"scope\": [\"constant.character\", \"constant.other\"],\n                \"settings\": {\n                    \"foreground\": \"#d19a66\"\n                }\n            },\n            {\n                \"name\": \"Language Variable\",\n                \"scope\": \"variable.language\",\n                \"settings\": {\n                    \"foreground\": \"#c678dd\"\n                }\n            },\n            {\n                \"name\": \"Variable\",\n                \"scope\": [\"variable.readwrite\", \"variable.block\", \"variable.support\"],\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Variable\",\n                \"scope\": \"variable.readwrite.var-single-variable.js\",\n                \"settings\": {\n                    \"foreground\": \"#d19a66\"\n                }\n            },\n            {\n                \"name\": \"Variable\",\n                \"scope\": \"variable.readwrite.js\",\n                \"settings\": {\n                    \"foreground\": \"#abb2bf\"\n                }\n            },\n            {\n                \"name\": \"Keyword\",\n                \"scope\": [\n                    \"keyword\",\n                    \"keyword.operator.logical\",\n                    \"keyword.operator.constructor\",\n                    \"keyword.operator.new\"\n                ],\n                \"settings\": {\n                    \"foreground\": \"#c678dd\"\n                }\n            },\n            {\n                \"name\": \"Keyword Operator\",\n                \"scope\": \"keyword.operator\",\n                \"settings\": {\n                    \"foreground\": \"#61afef\"\n                }\n            },\n            {\n                \"name\": \"Storage\",\n                \"scope\": \"storage\",\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#c678dd\"\n                }\n            },\n            {\n                \"name\": \"Storage type\",\n                \"scope\": \"storage.type.function\",\n                \"settings\": {\n                    \"foreground\": \"#c678dd\"\n                }\n            },\n            {\n                \"name\": \"Class name\",\n                \"scope\": [\"entity.name.class\", \"entity.name.module\", \"entity.name.type\"],\n                \"settings\": {\n                    \"foreground\": \"#e5c07b\"\n                }\n            },\n            {\n                \"name\": \"Inherited class\",\n                \"scope\": \"entity.other.inherited-class\",\n                \"settings\": {\n                    \"foreground\": \"#98c379\"\n                }\n            },\n            {\n                \"name\": \"Tag name\",\n                \"scope\": \"entity.name.tag\",\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Tag attribute\",\n                \"scope\": \"entity.other.attribute-name\",\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#d19a66\"\n                }\n            },\n            {\n                \"name\": \"Function name\",\n                \"scope\": \"entity.name.function\",\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#61afef\"\n                }\n            },\n            {\n                \"name\": \"Function argument\",\n                \"scope\": \"variable.parameter\",\n                \"settings\": {\n                    \"fontStyle\": \"italic\",\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Function call\",\n                \"scope\": \"entity.name.function-call\",\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#abb2bf\"\n                }\n            },\n            {\n                \"name\": \"Builtin Functions\",\n                \"scope\": [\"function.support.builtin\", \"function.support.core\"],\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#56b6c2\"\n                }\n            },\n            {\n                \"name\": \"Library function\",\n                \"scope\": \"support.function\",\n                \"settings\": {\n                    \"foreground\": \"#56b6c2\"\n                }\n            },\n            {\n                \"name\": \"Library constant\",\n                \"scope\": \"support.constant\",\n                \"settings\": {\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#e5c07b\"\n                }\n            },\n            {\n                \"name\": \"Library class/type\",\n                \"scope\": \"support.class\",\n                \"settings\": {\n                    \"foreground\": \"#e5c07b\"\n                }\n            },\n            {\n                \"name\": \"Library type\",\n                \"scope\": \"support.type\",\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Json Property\",\n                \"scope\": \"support.dictionary.json\",\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"StyleSheet Property name\",\n                \"scope\": [\n                    \"support.type.property-name.css\",\n                    \"support.type.property-name.scss\",\n                    \"support.type.property-name.less\",\n                    \"support.type.property-name.sass\"\n                ],\n                \"settings\": {\n                    \"foreground\": \"#abb2bf\"\n                }\n            },\n            {\n                \"name\": \"StyleSheet Property value\",\n                \"scope\": [\n                    \"support.constant.css\",\n                    \"support.constant.scss\",\n                    \"support.constant.less\",\n                    \"support.constant.sass\"\n                ],\n                \"settings\": {\n                    \"foreground\": \"#56b6c2\"\n                }\n            },\n            {\n                \"name\": \"StyleSheet Variable\",\n                \"scope\": [\"variable.css\", \"variable.scss\", \"variable.less\", \"variable.sass\"],\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"StyleSheet Variable String\",\n                \"scope\": [\n                    \"variable.css.string\",\n                    \"variable.scss.string\",\n                    \"variable.less.string\",\n                    \"variable.sass.string\"\n                ],\n                \"settings\": {\n                    \"foreground\": \"#98c379\"\n                }\n            },\n            {\n                \"name\": \"StyleSheet Unit\",\n                \"scope\": [\"unit.css\", \"unit.scss\", \"unit.less\", \"unit.sass\"],\n                \"settings\": {\n                    \"foreground\": \"#d19a66\"\n                }\n            },\n            {\n                \"name\": \"StyleSheet Function\",\n                \"scope\": [\"function.css\", \"function.scss\", \"function.less\", \"function.sass\"],\n                \"settings\": {\n                    \"foreground\": \"#56b6c2\"\n                }\n            },\n            {\n                \"name\": \"Other variable\",\n                \"scope\": [\n                    \"variable.other.property\",\n                    \"variable.other.object\",\n                    \"variable.other.block\"\n                ],\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Pug/Jade Import\",\n                \"scope\": [\"jade.import.variable\", \"pug.import.variable\"],\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Invalid\",\n                \"scope\": \"invalid\",\n                \"settings\": {\n                    \"background\": \"#c678dd\",\n                    \"fontStyle\": \"\",\n                    \"foreground\": \"#F8F8F0\"\n                }\n            },\n            {\n                \"name\": \"Invalid deprecated\",\n                \"scope\": \"invalid.deprecated\",\n                \"settings\": {\n                    \"background\": \"#56b6c2\",\n                    \"foreground\": \"#F8F8F0\"\n                }\n            },\n            {\n                \"name\": \"JSON String\",\n                \"scope\": \"structure.dictionary.property-name.json\",\n                \"settings\": {\n                    \"foreground\": \"#e06c75\"\n                }\n            },\n            {\n                \"name\": \"Link\",\n                \"scope\": \"string.detected-link\",\n                \"settings\": {\n                    \"foreground\": \"#c678dd\"\n                }\n            },\n            {\n                \"name\": \"diff.header\",\n                \"scope\": [\"meta.diff\", \"meta.diff.header\"],\n                \"settings\": {\n                    \"foreground\": \"#75715E\"\n                }\n            },\n            {\n                \"name\": \"diff.deleted\",\n                \"scope\": \"markup.deleted\",\n                \"settings\": {\n                    \"foreground\": \"#c678dd\"\n                }\n            },\n            {\n                \"name\": \"diff.inserted\",\n                \"scope\": \"markup.inserted\",\n                \"settings\": {\n                    \"foreground\": \"#e5c07b\"\n                }\n            },\n            {\n                \"name\": \"diff.changed\",\n                \"scope\": \"markup.changed\",\n                \"settings\": {\n                    \"foreground\": \"#98c379\"\n                }\n            },\n            {\n                \"scope\": \"constant.numeric.line-number.find-in-files - match\",\n                \"settings\": {\n                    \"foreground\": \"#56b6c2A0\"\n                }\n            },\n            {\n                \"scope\": \"entity.name.filename.find-in-files\",\n                \"settings\": {\n                    \"foreground\": \"#98c379\"\n                }\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "extensions/theme-onedark/colors/onedark.vim",
    "content": "\" Vim Color File\n\" Name:       onedark.vim\n\" Maintainer: https://github.com/joshdick/onedark.vim/\n\" License:    The MIT License (MIT)\n\" Based On:   https://github.com/MaxSt/FlatColor/\n\n\" A companion [vim-airline](https://github.com/bling/vim-airline) theme is available at: https://github.com/joshdick/airline-onedark.vim\n\n\" +-----------------+\n\" | Color Reference |\n\" +-----------------+\n\n\" The following colors were measured inside Atom using its built-in inspector.\n\n\" +---------------------------------------------+\n\" |  Color Name  |         RGB        |   Hex   |\n\" |--------------+--------------------+---------|\n\" | Black        | rgb(40, 44, 52)    | #282c34 |\n\" |--------------+--------------------+---------|\n\" | White        | rgb(171, 178, 191) | #abb2bf |\n\" |--------------+--------------------+---------|\n\" | Light Red    | rgb(224, 108, 117) | #e06c75 |\n\" |--------------+--------------------+---------|\n\" | Dark Red     | rgb(190, 80, 70)   | #be5046 |\n\" |--------------+--------------------+---------|\n\" | Green        | rgb(152, 195, 121) | #98c379 |\n\" |--------------+--------------------+---------|\n\" | Light Yellow | rgb(229, 192, 123) | #e5c07b |\n\" |--------------+--------------------+---------|\n\" | Dark Yellow  | rgb(209, 154, 102) | #d19a66 |\n\" |--------------+--------------------+---------|\n\" | Blue         | rgb(97, 175, 239)  | #61afef |\n\" |--------------+--------------------+---------|\n\" | Magenta      | rgb(198, 120, 221) | #c678dd |\n\" |--------------+--------------------+---------|\n\" | Cyan         | rgb(86, 182, 194)  | #56b6c2 |\n\" |--------------+--------------------+---------|\n\" | Gutter Grey  | rgb(99, 109, 131)  | #636d83 |\n\" |--------------+--------------------+---------|\n\" | Comment Grey | rgb(92, 99, 112)   | #5c6370 |\n\" +---------------------------------------------+\n\n\" +----------------+\n\" | Initialization |\n\" +----------------+\n\nset background=dark\n\nhighlight clear\n\nif exists(\"syntax_on\")\n  syntax reset\nendif\n\nset t_Co=256\n\nlet g:colors_name=\"onedark\"\n\n\" Set to \"256\" for 256-color terminals, or\n\" set to \"16\" to use your terminal emulator's native colors\n\" (a 16-color palette for this color scheme is available; see\n\" < https://github.com/joshdick/onedark.vim/blob/master/README.md >\n\" for more information.)\nif !exists(\"g:onedark_termcolors\")\n  let g:onedark_termcolors = 256\nendif\n\n\" Not all terminals support italics properly. If yours does, opt-in.\nif !exists(\"g:onedark_terminal_italics\")\n  let g:onedark_terminal_italics = 0\nendif\n\n\" This function is based on one from FlatColor: https://github.com/MaxSt/FlatColor/\n\" Which in turn was based on one found in hemisu: https://github.com/noahfrederick/vim-hemisu/\nfunction! s:h(group, style)\n  if g:onedark_terminal_italics == 0\n    if has_key(a:style, \"cterm\") && a:style[\"cterm\"] == \"italic\"\n      unlet a:style.cterm\n    endif\n    if has_key(a:style, \"gui\") && a:style[\"gui\"] == \"italic\"\n      unlet a:style.gui\n    endif\n  endif\n  if g:onedark_termcolors == 16\n    let l:ctermfg = (has_key(a:style, \"fg\") ? a:style.fg.cterm16 : \"NONE\")\n    let l:ctermbg = (has_key(a:style, \"bg\") ? a:style.bg.cterm16 : \"NONE\")\n  else\n    let l:ctermfg = (has_key(a:style, \"fg\") ? a:style.fg.cterm : \"NONE\")\n    let l:ctermbg = (has_key(a:style, \"bg\") ? a:style.bg.cterm : \"NONE\")\n  endif\n  execute \"highlight\" a:group\n    \\ \"guifg=\"   (has_key(a:style, \"fg\")    ? a:style.fg.gui   : \"NONE\")\n    \\ \"guibg=\"   (has_key(a:style, \"bg\")    ? a:style.bg.gui   : \"NONE\")\n    \\ \"guisp=\"   (has_key(a:style, \"sp\")    ? a:style.sp.gui   : \"NONE\")\n    \\ \"gui=\"     (has_key(a:style, \"gui\")   ? a:style.gui      : \"NONE\")\n    \\ \"ctermfg=\" . l:ctermfg\n    \\ \"ctermbg=\" . l:ctermbg\n    \\ \"cterm=\"   (has_key(a:style, \"cterm\") ? a:style.cterm    : \"NONE\")\nendfunction\n\n\" +-----------------+\n\" | Color Variables |\n\" +-----------------+\n\nlet s:red = { \"gui\": \"#E06C75\", \"cterm\": \"204\", \"cterm16\": \"1\" } \" Alternate cterm: 168\nlet s:dark_red = { \"gui\": \"#BE5046\", \"cterm\": \"196\", \"cterm16\": \"9\" }\n\nlet s:green = { \"gui\": \"#98C379\", \"cterm\": \"114\", \"cterm16\": \"2\" }\n\nlet s:yellow = { \"gui\": \"#E5C07B\", \"cterm\": \"180\", \"cterm16\": \"3\" }\nlet s:dark_yellow = { \"gui\": \"#D19A66\", \"cterm\": \"173\", \"cterm16\": \"11\" }\n\nlet s:blue = { \"gui\": \"#61AFEF\", \"cterm\": \"39\", \"cterm16\": \"4\" } \" Alternate cterm: 75\n\nlet s:purple = { \"gui\": \"#C678DD\", \"cterm\": \"170\", \"cterm16\": \"5\" } \" Alternate cterm: 176\n\nlet s:cyan = { \"gui\": \"#56B6C2\", \"cterm\": \"38\", \"cterm16\": \"6\" } \" Alternate cterm: 73\n\nlet s:white = { \"gui\": \"#ABB2BF\", \"cterm\": \"145\", \"cterm16\" : \"7\" }\n\nlet s:black = { \"gui\": \"#282C34\", \"cterm\": \"235\", \"cterm16\": \"0\" }\nlet s:visual_black = { \"gui\": \"NONE\", \"cterm\": \"NONE\", \"cterm16\": s:black.cterm16 } \" Black out selected text in 16-color visual mode\n\nlet s:comment_grey = { \"gui\": \"#5C6370\", \"cterm\": \"59\", \"cterm16\": \"15\" }\nlet s:gutter_fg_grey = { \"gui\": \"#636D83\", \"cterm\": \"238\", \"cterm16\": \"15\" }\nlet s:cursor_grey =  { \"gui\": \"#2C323C\", \"cterm\": \"236\", \"cterm16\": \"8\" }\nlet s:visual_grey = { \"gui\": \"#3E4452\", \"cterm\": \"237\", \"cterm16\": \"15\" }\nlet s:menu_grey = { \"gui\": s:visual_grey.gui, \"cterm\": s:visual_grey.cterm, \"cterm16\": \"8\" }\nlet s:special_grey = { \"gui\": \"#3B4048\", \"cterm\": \"238\", \"cterm16\": \"15\" }\nlet s:vertsplit = { \"gui\": \"#181A1F\", \"cterm\": \"59\", \"cterm16\": \"15\" }\n\n\" +---------------------------------------------------------+\n\" | Syntax Groups (descriptions and ordering from `:h w18`) |\n\" +---------------------------------------------------------+\n\ncall s:h(\"Comment\", { \"fg\": s:comment_grey, \"gui\": \"italic\", \"cterm\": \"italic\" }) \" any comment\ncall s:h(\"Constant\", { \"fg\": s:cyan }) \" any constant\ncall s:h(\"String\", { \"fg\": s:green }) \" a string constant: \"this is a string\"\ncall s:h(\"Character\", { \"fg\": s:green }) \" a character constant: 'c', '\\n'\ncall s:h(\"Number\", { \"fg\": s:dark_yellow }) \" a number constant: 234, 0xff\ncall s:h(\"Boolean\", { \"fg\": s:dark_yellow }) \" a boolean constant: TRUE, false\ncall s:h(\"Float\", { \"fg\": s:dark_yellow }) \" a floating point constant: 2.3e10\ncall s:h(\"Identifier\", { \"fg\": s:red }) \" any variable name\ncall s:h(\"Function\", { \"fg\": s:blue }) \" function name (also: methods for classes)\ncall s:h(\"Statement\", { \"fg\": s:purple }) \" any statement\ncall s:h(\"Conditional\", { \"fg\": s:purple }) \" if, then, else, endif, switch, etc.\ncall s:h(\"Repeat\", { \"fg\": s:purple }) \" for, do, while, etc.\ncall s:h(\"Label\", { \"fg\": s:purple }) \" case, default, etc.\ncall s:h(\"Operator\", { \"fg\": s:purple }) \" sizeof\", \"+\", \"*\", etc.\ncall s:h(\"Keyword\", { \"fg\": s:purple }) \" any other keyword\ncall s:h(\"Exception\", { \"fg\": s:purple }) \" try, catch, throw\ncall s:h(\"PreProc\", { \"fg\": s:yellow }) \" generic Preprocessor\ncall s:h(\"Include\", { \"fg\": s:blue }) \" preprocessor #include\ncall s:h(\"Define\", { \"fg\": s:purple }) \" preprocessor #define\ncall s:h(\"Macro\", { \"fg\": s:purple }) \" same as Define\ncall s:h(\"PreCondit\", { \"fg\": s:yellow }) \" preprocessor #if, #else, #endif, etc.\ncall s:h(\"Type\", { \"fg\": s:yellow }) \" int, long, char, etc.\ncall s:h(\"StorageClass\", { \"fg\": s:yellow }) \" static, register, volatile, etc.\ncall s:h(\"Structure\", { \"fg\": s:yellow }) \" struct, union, enum, etc.\ncall s:h(\"Typedef\", { \"fg\": s:yellow }) \" A typedef\ncall s:h(\"Special\", { \"fg\": s:blue }) \" any special symbol\ncall s:h(\"SpecialChar\", {}) \" special character in a constant\ncall s:h(\"Tag\", {}) \" you can use CTRL-] on this\ncall s:h(\"Delimiter\", {}) \" character that needs attention\ncall s:h(\"SpecialComment\", {}) \" special things inside a comment\ncall s:h(\"Debug\", {}) \" debugging statements\ncall s:h(\"Underlined\", {}) \" text that stands out, HTML links\ncall s:h(\"Ignore\", {}) \" left blank, hidden\ncall s:h(\"Error\", { \"fg\": s:red }) \" any erroneous construct\ncall s:h(\"Todo\", { \"fg\": s:purple }) \" anything that needs extra attention; mostly the keywords TODO FIXME and XXX\n\n\" +----------------------------------------------------------------------+\n\" | Highlighting Groups (descriptions and ordering from `:h hitest.vim`) |\n\" +----------------------------------------------------------------------+\n\ncall s:h(\"ColorColumn\", { \"bg\": s:cursor_grey }) \" used for the columns set with 'colorcolumn'\ncall s:h(\"Conceal\", {}) \" placeholder characters substituted for concealed text (see 'conceallevel')\ncall s:h(\"Cursor\", { \"fg\": s:black, \"bg\": s:blue }) \" the character under the cursor\ncall s:h(\"CursorIM\", {}) \" like Cursor, but used when in IME mode\ncall s:h(\"CursorColumn\", { \"bg\": s:cursor_grey }) \" the screen column that the cursor is in when 'cursorcolumn' is set\ncall s:h(\"CursorLine\", { \"bg\": s:cursor_grey }) \" the screen line that the cursor is in when 'cursorline' is set\ncall s:h(\"Directory\", { \"fg\": s:blue }) \" directory names (and other special names in listings)\ncall s:h(\"DiffAdd\", { \"bg\": s:visual_grey}) \" diff mode: Added line\ncall s:h(\"DiffChange\", { \"bg\": s:visual_grey }) \" diff mode: Changed line\ncall s:h(\"DiffDelete\", { \"fg\": s:red }) \" diff mode: Deleted line\ncall s:h(\"DiffText\", { \"bg\": s:visual_grey, \"fg\": s:yellow }) \" diff mode: Changed text within a changed line\ncall s:h(\"ErrorMsg\", {}) \" error messages on the command line\ncall s:h(\"VertSplit\", { \"fg\": s:vertsplit }) \" the column separating vertically split windows\ncall s:h(\"Folded\", { \"fg\": s:comment_grey }) \" line used for closed folds\ncall s:h(\"FoldColumn\", {}) \" 'foldcolumn'\ncall s:h(\"SignColumn\", {}) \" column where signs are displayed\ncall s:h(\"IncSearch\", { \"fg\": s:black, \"bg\": s:yellow }) \" 'incsearch' highlighting; also used for the text replaced with \":s///c\"\ncall s:h(\"LineNr\", { \"fg\": s:gutter_fg_grey }) \" Line number for \":number\" and \":#\" commands, and when 'number' or 'relativenumber' option is set.\ncall s:h(\"CursorLineNr\", {}) \" Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line.\ncall s:h(\"MatchParen\", { \"fg\": s:blue, \"gui\": \"underline\" }) \" The character under the cursor or just before it, if it is a paired bracket, and its match.\ncall s:h(\"ModeMsg\", {}) \" 'showmode' message (e.g., \"-- INSERT --\")\ncall s:h(\"MoreMsg\", {}) \" more-prompt\ncall s:h(\"NonText\", { \"fg\": s:special_grey }) \" '~' and '@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., \">\" displayed when a double-wide character doesn't fit at the end of the line).\ncall s:h(\"Normal\", { \"fg\": s:white, \"bg\": s:black }) \" normal text\ncall s:h(\"Pmenu\", { \"bg\": s:menu_grey }) \" Popup menu: normal item.\ncall s:h(\"PmenuSel\", { \"bg\": s:black }) \" Popup menu: selected item.\ncall s:h(\"PmenuSbar\", { \"bg\": s:special_grey }) \" Popup menu: scrollbar.\ncall s:h(\"PmenuThumb\", { \"bg\": s:white }) \" Popup menu: Thumb of the scrollbar.\ncall s:h(\"Question\", { \"fg\": s:purple }) \" hit-enter prompt and yes/no questions\ncall s:h(\"Search\", { \"fg\": s:black, \"bg\": s:yellow }) \" Last search pattern highlighting (see 'hlsearch'). Also used for highlighting the current line in the quickfix window and similar items that need to stand out.\ncall s:h(\"SpecialKey\", { \"fg\": s:special_grey }) \" Meta and special keys listed with \":map\", also for text used to show unprintable characters in the text, 'listchars'. Generally: text that is displayed differently from what it really is.\ncall s:h(\"SpellBad\", { \"fg\": s:red, \"gui\": \"underline\", \"cterm\": \"underline\" }) \" Word that is not recognized by the spellchecker. This will be combined with the highlighting used otherwise.\ncall s:h(\"SpellCap\", { \"fg\": s:dark_yellow }) \" Word that should start with a capital. This will be combined with the highlighting used otherwise.\ncall s:h(\"SpellLocal\", { \"fg\": s:dark_yellow }) \" Word that is recognized by the spellchecker as one that is used in another region. This will be combined with the highlighting used otherwise.\ncall s:h(\"SpellRare\", { \"fg\": s:dark_yellow }) \" Word that is recognized by the spellchecker as one that is hardly ever used. spell This will be combined with the highlighting used otherwise.\ncall s:h(\"StatusLine\", { \"fg\": s:white, \"bg\": s:cursor_grey }) \" status line of current window\ncall s:h(\"StatusLineNC\", { \"fg\": s:comment_grey }) \" status lines of not-current windows Note: if this is equal to \"StatusLine\" Vim will use \"^^^\" in the status line of the current window.\ncall s:h(\"TabLine\", { \"fg\": s:comment_grey }) \" tab pages line, not active tab page label\ncall s:h(\"TabLineFill\", {}) \" tab pages line, where there are no labels\ncall s:h(\"TabLineSel\", { \"fg\": s:white }) \" tab pages line, active tab page label\ncall s:h(\"Title\", { \"fg\": s:green }) \" titles for output from \":set all\", \":autocmd\" etc.\ncall s:h(\"Visual\", { \"fg\": s:visual_black, \"bg\": s:visual_grey }) \" Visual mode selection\ncall s:h(\"VisualNOS\", { \"bg\": s:visual_grey }) \" Visual mode selection when vim is \"Not Owning the Selection\". Only X11 Gui's gui-x11 and xterm-clipboard supports this.\ncall s:h(\"WarningMsg\", { \"fg\": s:red }) \" warning messages\ncall s:h(\"WildMenu\", {}) \" current match in 'wildmenu' completion\n\n\" +--------------------------------+\n\" | Language-Specific Highlighting |\n\" +--------------------------------+\n\n\" CSS\ncall s:h(\"cssAttrComma\", { \"fg\": s:purple })\ncall s:h(\"cssAttributeSelector\", { \"fg\": s:green })\ncall s:h(\"cssBraces\", { \"fg\": s:white })\ncall s:h(\"cssClassName\", { \"fg\": s:dark_yellow })\ncall s:h(\"cssClassNameDot\", { \"fg\": s:dark_yellow })\ncall s:h(\"cssDefinition\", { \"fg\": s:purple })\ncall s:h(\"cssFontAttr\", { \"fg\": s:dark_yellow })\ncall s:h(\"cssFontDescriptor\", { \"fg\": s:purple })\ncall s:h(\"cssFunctionName\", { \"fg\": s:blue })\ncall s:h(\"cssIdentifier\", { \"fg\": s:blue })\ncall s:h(\"cssImportant\", { \"fg\": s:purple })\ncall s:h(\"cssInclude\", { \"fg\": s:white })\ncall s:h(\"cssIncludeKeyword\", { \"fg\": s:purple })\ncall s:h(\"cssMediaType\", { \"fg\": s:dark_yellow })\ncall s:h(\"cssProp\", { \"fg\": s:white })\ncall s:h(\"cssPseudoClassId\", { \"fg\": s:dark_yellow })\ncall s:h(\"cssSelectorOp\", { \"fg\": s:purple })\ncall s:h(\"cssSelectorOp2\", { \"fg\": s:purple })\ncall s:h(\"cssTagName\", { \"fg\": s:red })\n\n\" HTML\ncall s:h(\"htmlTitle\", { \"fg\": s:white })\ncall s:h(\"htmlArg\", { \"fg\": s:dark_yellow })\ncall s:h(\"htmlEndTag\", { \"fg\": s:white })\ncall s:h(\"htmlH1\", { \"fg\": s:white })\ncall s:h(\"htmlLink\", { \"fg\": s:purple })\ncall s:h(\"htmlSpecialChar\", { \"fg\": s:dark_yellow })\ncall s:h(\"htmlSpecialTagName\", { \"fg\": s:red })\ncall s:h(\"htmlTag\", { \"fg\": s:white })\ncall s:h(\"htmlTagName\", { \"fg\": s:red })\n\n\" JavaScript\ncall s:h(\"javaScriptBraces\", { \"fg\": s:white })\ncall s:h(\"javaScriptFunction\", { \"fg\": s:purple })\ncall s:h(\"javaScriptIdentifier\", { \"fg\": s:purple })\ncall s:h(\"javaScriptNull\", { \"fg\": s:dark_yellow })\ncall s:h(\"javaScriptNumber\", { \"fg\": s:dark_yellow })\ncall s:h(\"javaScriptRequire\", { \"fg\": s:cyan })\ncall s:h(\"javaScriptReserved\", { \"fg\": s:purple })\n\" https://github.com/pangloss/vim-javascript\ncall s:h(\"jsArrowFunction\", { \"fg\": s:purple })\ncall s:h(\"jsClassKeywords\", { \"fg\": s:purple })\ncall s:h(\"jsDocParam\", { \"fg\": s:blue })\ncall s:h(\"jsDocTags\", { \"fg\": s:purple })\ncall s:h(\"jsFuncCall\", { \"fg\": s:blue })\ncall s:h(\"jsFunction\", { \"fg\": s:purple })\ncall s:h(\"jsGlobalObjects\", { \"fg\": s:yellow })\ncall s:h(\"jsModuleWords\", { \"fg\": s:purple })\ncall s:h(\"jsModules\", { \"fg\": s:purple })\ncall s:h(\"jsNull\", { \"fg\": s:dark_yellow })\ncall s:h(\"jsOperator\", { \"fg\": s:purple })\ncall s:h(\"jsStorageClass\", { \"fg\": s:purple })\ncall s:h(\"jsTemplateBraces\", { \"fg\": s:dark_red })\ncall s:h(\"jsTemplateVar\", { \"fg\": s:green })\ncall s:h(\"jsThis\", { \"fg\": s:red })\ncall s:h(\"jsUndefined\", { \"fg\": s:dark_yellow })\n\" https://github.com/othree/yajs.vim\ncall s:h(\"javascriptArrowFunc\", { \"fg\": s:purple })\ncall s:h(\"javascriptClassExtends\", { \"fg\": s:purple })\ncall s:h(\"javascriptClassKeyword\", { \"fg\": s:purple })\ncall s:h(\"javascriptDocNotation\", { \"fg\": s:purple })\ncall s:h(\"javascriptDocParamName\", { \"fg\": s:blue })\ncall s:h(\"javascriptDocTags\", { \"fg\": s:purple })\ncall s:h(\"javascriptEndColons\", { \"fg\": s:white })\ncall s:h(\"javascriptExport\", { \"fg\": s:purple })\ncall s:h(\"javascriptFuncArg\", { \"fg\": s:white })\ncall s:h(\"javascriptFuncKeyword\", { \"fg\": s:purple })\ncall s:h(\"javascriptIdentifier\", { \"fg\": s:red })\ncall s:h(\"javascriptImport\", { \"fg\": s:purple })\ncall s:h(\"javascriptObjectLabel\", { \"fg\": s:white })\ncall s:h(\"javascriptOpSymbol\", { \"fg\": s:cyan })\ncall s:h(\"javascriptOpSymbols\", { \"fg\": s:cyan })\ncall s:h(\"javascriptPropertyName\", { \"fg\": s:green })\ncall s:h(\"javascriptTemplateSB\", { \"fg\": s:dark_red })\ncall s:h(\"javascriptVariable\", { \"fg\": s:purple })\n\n\" JSON\ncall s:h(\"jsonCommentError\", { \"fg\": s:white })\ncall s:h(\"jsonKeyword\", { \"fg\": s:red })\ncall s:h(\"jsonBoolean\", { \"fg\": s:dark_yellow })\ncall s:h(\"jsonNumber\", { \"fg\": s:dark_yellow })\ncall s:h(\"jsonQuote\", { \"fg\": s:white })\ncall s:h(\"jsonMissingCommaError\", { \"fg\": s:red, \"gui\": \"reverse\" })\ncall s:h(\"jsonNoQuotesError\", { \"fg\": s:red, \"gui\": \"reverse\" })\ncall s:h(\"jsonNumError\", { \"fg\": s:red, \"gui\": \"reverse\" })\ncall s:h(\"jsonString\", { \"fg\": s:green })\ncall s:h(\"jsonStringSQError\", { \"fg\": s:red, \"gui\": \"reverse\" })\ncall s:h(\"jsonSemicolonError\", { \"fg\": s:red, \"gui\": \"reverse\" })\n\n\" Markdown\ncall s:h(\"markdownCode\", { \"fg\": s:green })\ncall s:h(\"markdownCodeBlock\", { \"fg\": s:green })\ncall s:h(\"markdownCodeDelimiter\", { \"fg\": s:green })\ncall s:h(\"markdownHeadingDelimiter\", { \"fg\": s:red })\ncall s:h(\"markdownRule\", { \"fg\": s:comment_grey })\ncall s:h(\"markdownHeadingRule\", { \"fg\": s:comment_grey })\ncall s:h(\"markdownH1\", { \"fg\": s:red })\ncall s:h(\"markdownH2\", { \"fg\": s:red })\ncall s:h(\"markdownH3\", { \"fg\": s:red })\ncall s:h(\"markdownH4\", { \"fg\": s:red })\ncall s:h(\"markdownH5\", { \"fg\": s:red })\ncall s:h(\"markdownH6\", { \"fg\": s:red })\ncall s:h(\"markdownIdDelimiter\", { \"fg\": s:purple })\ncall s:h(\"markdownId\", { \"fg\": s:purple })\ncall s:h(\"markdownBlockquote\", { \"fg\": s:comment_grey })\ncall s:h(\"markdownItalic\", { \"fg\": s:purple, \"gui\": \"italic\", \"cterm\": \"italic\" })\ncall s:h(\"markdownBold\", { \"fg\": s:dark_yellow, \"gui\": \"bold\", \"cterm\": \"bold\" })\ncall s:h(\"markdownListMarker\", { \"fg\": s:red })\ncall s:h(\"markdownOrderedListMarker\", { \"fg\": s:red })\ncall s:h(\"markdownIdDeclaration\", { \"fg\": s:blue })\ncall s:h(\"markdownLinkText\", { \"fg\": s:blue })\ncall s:h(\"markdownLinkDelimiter\", { \"fg\": s:white })\ncall s:h(\"markdownUrl\", { \"fg\": s:purple })\n\n\" Ruby\ncall s:h(\"rubyBlockParameter\", { \"fg\": s:red})\ncall s:h(\"rubyBlockParameterList\", { \"fg\": s:red })\ncall s:h(\"rubyClass\", { \"fg\": s:purple})\ncall s:h(\"rubyConstant\", { \"fg\": s:yellow})\ncall s:h(\"rubyControl\", { \"fg\": s:purple })\ncall s:h(\"rubyEscape\", { \"fg\": s:red})\ncall s:h(\"rubyFunction\", { \"fg\": s:blue})\ncall s:h(\"rubyGlobalVariable\", { \"fg\": s:red})\ncall s:h(\"rubyInclude\", { \"fg\": s:blue})\ncall s:h(\"rubyIncluderubyGlobalVariable\", { \"fg\": s:red})\ncall s:h(\"rubyInstanceVariable\", { \"fg\": s:red})\ncall s:h(\"rubyInterpolation\", { \"fg\": s:cyan })\ncall s:h(\"rubyInterpolationDelimiter\", { \"fg\": s:red })\ncall s:h(\"rubyInterpolationDelimiter\", { \"fg\": s:red})\ncall s:h(\"rubyRegexp\", { \"fg\": s:cyan})\ncall s:h(\"rubyRegexpDelimiter\", { \"fg\": s:cyan})\ncall s:h(\"rubyStringDelimiter\", { \"fg\": s:green})\ncall s:h(\"rubySymbol\", { \"fg\": s:cyan})\n\n\" Sass\ncall s:h(\"sassAmpersand\", { \"fg\": s:red })\ncall s:h(\"sassClass\", { \"fg\": s:dark_yellow })\ncall s:h(\"sassControl\", { \"fg\": s:purple })\ncall s:h(\"sassExtend\", { \"fg\": s:purple })\ncall s:h(\"sassFor\", { \"fg\": s:white })\ncall s:h(\"sassFunction\", { \"fg\": s:cyan })\ncall s:h(\"sassId\", { \"fg\": s:blue })\ncall s:h(\"sassInclude\", { \"fg\": s:purple })\ncall s:h(\"sassMedia\", { \"fg\": s:purple })\ncall s:h(\"sassMediaOperators\", { \"fg\": s:white })\ncall s:h(\"sassMixin\", { \"fg\": s:purple })\ncall s:h(\"sassMixinName\", { \"fg\": s:blue })\ncall s:h(\"sassMixing\", { \"fg\": s:purple })\n\n\" TypeScript\ncall s:h(\"typescriptReserved\", { \"fg\": s:purple })\ncall s:h(\"typescriptEndColons\", { \"fg\": s:white })\ncall s:h(\"typescriptBraces\", { \"fg\": s:white })\n\n\" XML\ncall s:h(\"xmlAttrib\", { \"fg\": s:dark_yellow })\ncall s:h(\"xmlEndTag\", { \"fg\": s:red })\ncall s:h(\"xmlTag\", { \"fg\": s:red })\ncall s:h(\"xmlTagName\", { \"fg\": s:red })\n\n\" +---------------------+\n\" | Plugin Highlighting |\n\" +---------------------+\n\n\" airblade/vim-gitgutter\nhi link GitGutterAdd    SignifySignAdd\nhi link GitGutterChange SignifySignChange\nhi link GitGutterDelete SignifySignDelete\n\n\" mhinz/vim-signify\ncall s:h(\"SignifySignAdd\", { \"fg\": s:green })\ncall s:h(\"SignifySignChange\", { \"fg\": s:yellow })\ncall s:h(\"SignifySignDelete\", { \"fg\": s:red })\n\n\" neomake/neomake\ncall s:h(\"NeomakeWarningSign\", { \"fg\": s:yellow })\ncall s:h(\"NeomakeErrorSign\", { \"fg\": s:red })\ncall s:h(\"NeomakeInfoSign\", { \"fg\": s:blue })\n\n\" tpope/vim-fugitive\ncall s:h(\"diffAdded\", { \"fg\": s:green })\ncall s:h(\"diffRemoved\", { \"fg\": s:red })\n\n\" +------------------+\n\" | Git Highlighting |\n\" +------------------+\n\ncall s:h(\"gitcommitComment\", { \"fg\": s:comment_grey })\ncall s:h(\"gitcommitUnmerged\", { \"fg\": s:green })\ncall s:h(\"gitcommitOnBranch\", {})\ncall s:h(\"gitcommitBranch\", { \"fg\": s:purple })\ncall s:h(\"gitcommitDiscardedType\", { \"fg\": s:red })\ncall s:h(\"gitcommitSelectedType\", { \"fg\": s:green })\ncall s:h(\"gitcommitHeader\", {})\ncall s:h(\"gitcommitUntrackedFile\", { \"fg\": s:cyan })\ncall s:h(\"gitcommitDiscardedFile\", { \"fg\": s:red })\ncall s:h(\"gitcommitSelectedFile\", { \"fg\": s:green })\ncall s:h(\"gitcommitUnmergedFile\", { \"fg\": s:yellow })\ncall s:h(\"gitcommitFile\", {})\nhi link gitcommitNoBranch gitcommitBranch\nhi link gitcommitUntracked gitcommitComment\nhi link gitcommitDiscarded gitcommitComment\nhi link gitcommitSelected gitcommitComment\nhi link gitcommitDiscardedArrow gitcommitDiscardedFile\nhi link gitcommitSelectedArrow gitcommitSelectedFile\nhi link gitcommitUnmergedArrow gitcommitUnmergedFile\n\n\" +------------------------+\n\" | Neovim terminal colors |\n\" +------------------------+\n\nif has(\"nvim\")\n  let g:terminal_color_0 =  s:black.gui\n  let g:terminal_color_1 =  s:red.gui\n  let g:terminal_color_2 =  s:green.gui\n  let g:terminal_color_3 =  s:yellow.gui\n  let g:terminal_color_4 =  s:blue.gui\n  let g:terminal_color_5 =  s:purple.gui\n  let g:terminal_color_6 =  s:cyan.gui\n  let g:terminal_color_7 =  s:white.gui\n  let g:terminal_color_8 =  s:visual_grey.gui\n  let g:terminal_color_9 =  s:dark_red.gui\n  let g:terminal_color_10 = s:green.gui \" No dark version\n  let g:terminal_color_11 = s:dark_yellow.gui\n  let g:terminal_color_12 = s:blue.gui \" No dark version\n  let g:terminal_color_13 = s:purple.gui \" No dark version\n  let g:terminal_color_14 = s:cyan.gui \" No dark version\n  let g:terminal_color_15 = s:comment_grey.gui\n  let g:terminal_color_background = g:terminal_color_0\n  let g:terminal_color_foreground = g:terminal_color_7\nendif\n"
  },
  {
    "path": "extensions/theme-onedark/package.json",
    "content": "{\n    \"name\": \"theme-onedark\",\n    \"version\": \"0.0.1\",\n    \"description\": \"One-dark theme, set for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"themes\": [\n            {\n                \"name\": \"onedark\",\n                \"path\": \"colors/onedark.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/theme-solarized/colors/solarized8.vim",
    "content": "\" Name:         Solarized 8\n\" Description:  Precision colors for machines and people\n\" Author:       Ethan Schoonover\n\" Maintainer:   Lifepillar <lifepillar@lifepillar.me>\n\" Website:      https://github.com/lifepillar/vim-solarized8\n\" License:      OSI approved MIT license\n\" Last Updated: Wed Nov 29 19:34:14 2017\n\nif !(has('termguicolors') && &termguicolors) && !has('gui_running')\n      \\ && (!exists('&t_Co') || &t_Co < (get(g:, 'solarized_use16', 0) ? 16 : 256))\n  echoerr '[Solarized 8] There are not enough colors.'\n  finish\nendif\n\nhi clear\nif exists('syntax_on')\n  syntax reset\nendif\n\nlet g:colors_name = 'solarized8'\n\n\" 256-color variant\nif !get(g:, 'solarized_use16', 0)\n  if &background ==# 'dark'\n    \" Color similarity table (dark background)\n    \"  yellow: GUI=#b58900/rgb(181,137,  0)  Term=136 #af8700/rgb(175,135,  0)  [delta=1.465279]\n    \"    blue: GUI=#268bd2/rgb( 38,139,210)  Term= 32 #0087d7/rgb(  0,135,215)  [delta=2.677029]\n    \" magenta: GUI=#d33682/rgb(211, 54,130)  Term=162 #d70087/rgb(215,  0,135)  [delta=4.342643]\n    \"    cyan: GUI=#2aa198/rgb( 42,161,152)  Term= 37 #00afaf/rgb(  0,175,175)  [delta=5.365780]\n    \"   base1: GUI=#93a1a1/rgb(147,161,161)  Term=247 #9e9e9e/rgb(158,158,158)  [delta=6.489730]\n    \"  violet: GUI=#6c71c4/rgb(108,113,196)  Term= 61 #5f5faf/rgb( 95, 95,175)  [delta=6.795109]\n    \"     red: GUI=#dc322f/rgb(220, 50, 47)  Term=160 #d70000/rgb(215,  0,  0)  [delta=6.843619]\n    \"   green: GUI=#859900/rgb(133,153,  0)  Term=106 #87af00/rgb(135,175,  0)  [delta=6.901386]\n    \"   base0: GUI=#839496/rgb(131,148,150)  Term=246 #949494/rgb(148,148,148)  [delta=7.557606]\n    \"   base3: GUI=#fdf6e3/rgb(253,246,227)  Term=230 #ffffd7/rgb(255,255,215)  [delta=7.816259]\n    \"  orange: GUI=#cb4b16/rgb(203, 75, 22)  Term=166 #d75f00/rgb(215, 95,  0)  [delta=8.065025]\n    \"   base2: GUI=#eee8d5/rgb(238,232,213)  Term=254 #e4e4e4/rgb(228,228,228)  [delta=8.289679]\n    \"  base00: GUI=#657b83/rgb(101,123,131)  Term= 66 #5f8787/rgb( 95,135,135)  [delta=8.468738]\n    \"  base01: GUI=#586e75/rgb( 88,110,117)  Term=242 #6c6c6c/rgb(108,108,108)  [delta=9.227744]\n    \"    back: GUI=#002b36/rgb(  0, 43, 54)  Term=235 #262626/rgb( 38, 38, 38)  [delta=12.727247]\n    \"  base03: GUI=#002b36/rgb(  0, 43, 54)  Term=235 #262626/rgb( 38, 38, 38)  [delta=12.727247]\n    \"  base02: GUI=#073642/rgb(  7, 54, 66)  Term=236 #303030/rgb( 48, 48, 48)  [delta=13.434724]\n    if !has('gui_running') && get(g:, 'solarized_termtrans', 0)\n      hi Normal ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi FoldColumn ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi Folded ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=#002b36 cterm=NONE,bold gui=NONE,bold\n      hi LineNr ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi Terminal ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi CursorLineNr ctermbg=NONE guifg=NONE\n    else\n      hi Normal ctermfg=246 ctermbg=235 guifg=#839496 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi FoldColumn ctermfg=246 ctermbg=236 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n      hi Folded ctermfg=246 ctermbg=236 guifg=#839496 guibg=#073642 guisp=#002b36 cterm=NONE,bold gui=NONE,bold\n      hi LineNr ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n      hi Terminal ctermfg=fg ctermbg=235 guifg=fg guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi CursorLineNr ctermbg=236 guibg=#073642\n    endif\n    if get(g:, \"solarized_visibility\", \"\") == \"high\"\n      hi CursorLineNr ctermfg=166 guifg=#cb4b16 cterm=bold gui=bold\n      hi NonText ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi SpecialKey ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi SpellBad ctermfg=61 ctermbg=230 guifg=#6c71c4 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n      hi SpellCap ctermfg=61 ctermbg=230 guifg=#6c71c4 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n      hi SpellLocal ctermfg=136 ctermbg=230 guifg=#b58900 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n      hi SpellRare ctermfg=37 ctermbg=230 guifg=#2aa198 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n      hi Title ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    elseif get(g:, \"solarized_visibility\", \"\") == \"low\"\n      hi CursorLineNr ctermfg=242 guifg=#586e75 cterm=bold gui=bold\n      hi NonText ctermfg=236 ctermbg=NONE guifg=#073642 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi SpecialKey ctermfg=236 ctermbg=NONE guifg=#073642 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi SpellBad ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n      hi SpellCap ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n      hi SpellLocal ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n      hi SpellRare ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n      hi Title ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    else\n      hi CursorLineNr ctermfg=246 guifg=#839496 cterm=bold gui=bold\n      hi NonText ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi SpecialKey ctermfg=66 ctermbg=236 guifg=#657b83 guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi SpellBad ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n      hi SpellCap ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n      hi SpellLocal ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n      hi SpellRare ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n      hi Title ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    endif\n    hi ColorColumn ctermfg=NONE ctermbg=236 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n    hi Conceal ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    if get(g:, 'solarized_old_cursor_style', 0)\n      hi Cursor ctermfg=235 ctermbg=246 guifg=#002b36 guibg=#839496 guisp=NONE cterm=NONE gui=NONE\n    else\n      hi Cursor ctermfg=230 ctermbg=32 guifg=#fdf6e3 guibg=#268bd2 guisp=NONE cterm=NONE gui=NONE\n    endif\n    hi CursorColumn ctermfg=NONE ctermbg=236 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n    hi CursorLine ctermfg=NONE ctermbg=236 guifg=NONE guibg=#073642 guisp=#93a1a1 cterm=NONE gui=NONE\n    if get(g:, \"solarized_diffmode\", \"\") == \"high\"\n      hi DiffAdd ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi DiffChange ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi DiffDelete ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi DiffText ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    elseif get(g:, \"solarized_diffmode\", \"\") == \"low\"\n      hi DiffAdd ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=#859900 cterm=NONE gui=NONE\n      hi DiffChange ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE gui=NONE\n      hi DiffDelete ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi DiffText ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=#268bd2 cterm=NONE gui=NONE\n    else\n      hi DiffAdd ctermfg=106 ctermbg=236 guifg=#859900 guibg=#073642 guisp=#859900 cterm=NONE gui=NONE\n      hi DiffChange ctermfg=136 ctermbg=236 guifg=#b58900 guibg=#073642 guisp=#b58900 cterm=NONE gui=NONE\n      hi DiffDelete ctermfg=160 ctermbg=236 guifg=#dc322f guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi DiffText ctermfg=32 ctermbg=236 guifg=#268bd2 guibg=#073642 guisp=#268bd2 cterm=NONE gui=NONE\n    endif\n    hi Directory ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi EndOfBuffer ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi ErrorMsg ctermfg=160 ctermbg=230 guifg=#dc322f guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi IncSearch ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n    hi MatchParen ctermfg=230 ctermbg=236 guifg=#fdf6e3 guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi ModeMsg ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi MoreMsg ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi Pmenu ctermfg=246 ctermbg=236 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi PmenuSbar ctermfg=254 ctermbg=246 guifg=#eee8d5 guibg=#839496 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi PmenuSel ctermfg=242 ctermbg=254 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi PmenuThumb ctermfg=246 ctermbg=235 guifg=#839496 guibg=#002b36 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi Question ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link QuickFixLine Search\n    hi Search ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi SignColumn ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    if get(g:, \"solarized_statusline\", \"\") == \"low\"\n      hi StatusLine ctermfg=242 ctermbg=254 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi StatusLineNC ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi TabLine ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi TabLineFill ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi TabLineSel ctermfg=246 ctermbg=230 guifg=#839496 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    else\n      hi StatusLine ctermfg=246 ctermbg=236 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi StatusLineNC ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi TabLine ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi TabLineFill ctermfg=242 ctermbg=236 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi TabLineSel ctermfg=246 ctermbg=236 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    endif\n    hi! link StatusLineTerm StatusLine\n    hi! link StatusLineTermNC StatusLineNC\n    hi VertSplit ctermfg=242 ctermbg=242 guifg=#586e75 guibg=#586e75 guisp=NONE cterm=NONE gui=NONE\n    hi Visual ctermfg=242 ctermbg=235 guifg=#586e75 guibg=#002b36 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi VisualNOS ctermfg=NONE ctermbg=236 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi WarningMsg ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi WildMenu ctermfg=254 ctermbg=236 guifg=#eee8d5 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi! link Boolean Constant\n    hi! link Character Constant\n    hi Comment ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi! link Conditional Statement\n    hi Constant ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link Define PreProc\n    hi! link Debug Special\n    hi! link Delimiter Special\n    hi Error ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link Exception Statement\n    hi! link Float Constant\n    hi! link Function Identifier\n    hi Identifier ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi Ignore ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link Include PreProc\n    hi! link Keyword Statement\n    hi! link Label Statement\n    hi! link Macro PreProc\n    hi! link Number Constant\n    hi! link Operator Statement\n    hi! link PreCondit PreProc\n    hi PreProc ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link Repeat Statement\n    hi Special ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link SpecialChar Special\n    hi! link SpecialComment Special\n    hi Statement ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link StorageClass Type\n    hi! link String Constant\n    hi! link Structure Type\n    hi! link Tag Special\n    hi Todo ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi Type ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link Typedef Type\n    hi Underlined ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link lCursor Cursor\n    hi CursorIM ctermfg=NONE ctermbg=fg guifg=NONE guibg=fg guisp=NONE cterm=NONE gui=NONE\n    hi ToolbarLine ctermfg=NONE ctermbg=236 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n    hi ToolbarButton ctermfg=247 ctermbg=236 guifg=#93a1a1 guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi NormalMode ctermfg=246 ctermbg=230 guifg=#839496 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi InsertMode ctermfg=37 ctermbg=230 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi ReplaceMode ctermfg=166 ctermbg=230 guifg=#cb4b16 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi VisualMode ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi CommandMode ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    if get(g:, 'solarized_extra_hi_groups', 0)\n      hi! link vimVar Identifier\n      hi! link vimFunc Function\n      hi! link vimUserFunc Function\n      hi! link helpSpecial Special\n      hi! link vimSet Normal\n      hi! link vimSetEqual Normal\n      hi vimCommentString ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimCommand ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimCmdSep ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi helpExample ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi helpOption ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi helpNote ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi helpVim ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi helpHyperTextJump ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi helpHyperTextEntry ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimIsCommand ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimSynMtchOpt ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimSynType ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimHiLink ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimHiGroup ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi vimGroup ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi! link diffAdded Statement\n      hi! link diffLine Identifier\n      hi gitcommitComment ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n      hi! link gitcommitUntracked gitcommitComment\n      hi! link gitcommitDiscarded gitcommitComment\n      hi! link gitcommitSelected gitcommitComment\n      hi gitcommitUnmerged ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi gitcommitOnBranch ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi gitcommitBranch ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi! link gitcommitNoBranch gitcommitBranch\n      hi gitcommitdiscardedtype ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi gitcommitselectedtype ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi gitcommitHeader ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi gitcommitUntrackedFile ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi gitcommitDiscardedFile ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi gitcommitSelectedFile ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi gitcommitUnmergedFile ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi gitcommitFile ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi! link gitcommitDiscardedArrow gitcommitDiscardedFile\n      hi! link gitcommitSelectedArrow gitcommitSelectedFile\n      hi! link gitcommitUnmergedArrow gitcommitUnmergedFile\n      hi htmlTag ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi htmlEndTag ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi htmlTagN ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi htmlTagName ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi htmlSpecialTagName ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n      hi htmlArg ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi javaScript ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi perlHereDoc ctermfg=247 ctermbg=235 guifg=#93a1a1 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi perlVarPlain ctermfg=136 ctermbg=235 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi perlStatementFileDesc ctermfg=37 ctermbg=235 guifg=#2aa198 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi texstatement ctermfg=37 ctermbg=235 guifg=#2aa198 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi texmathzonex ctermfg=136 ctermbg=235 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi texmathmatcher ctermfg=136 ctermbg=235 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi texreflabel ctermfg=136 ctermbg=235 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi rubyDefine ctermfg=247 ctermbg=235 guifg=#93a1a1 guibg=#002b36 guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi! link rubySymbol Type\n      hi rubyBoolean ctermfg=162 ctermbg=235 guifg=#d33682 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      let hs_highlight_boolean=1\n      let hs_highlight_delimiters=1\n      hi cPreCondit ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi VarId ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi ConId ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsImport ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsString ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsStructure ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hs_hlFunctionName ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsStatement ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsImportLabel ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hs_OpFunctionName ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hs_DeclareFunction ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsVarSym ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsType ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsTypedef ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsModuleName ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi! link hsImportParams Delimiter\n      hi! link hsDelimTypeExport Delimiter\n      hi! link hsModuleStartLabel hsStructure\n      hi! link hsModuleWhereLabel hsModuleStartLabel\n      hi hsNiceOperator ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi hsniceoperator ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocTitleBlock ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocTitleBlockTitle ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocTitleComment ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocComment ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n      hi pandocVerbatimBlock ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi! link pandocVerbatimBlockDeep pandocVerbatimBlock\n      hi! link pandocCodeBlock pandocVerbatimBlock\n      hi! link pandocCodeBlockDelim pandocVerbatimBlock\n      hi pandocBlockQuote ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocBlockQuoteLeader1 ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocBlockQuoteLeader2 ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocBlockQuoteLeader3 ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocBlockQuoteLeader4 ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocBlockQuoteLeader5 ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocBlockQuoteLeader6 ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocListMarker ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocListReference ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocDefinitionBlock ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocDefinitionTerm ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n      hi pandocDefinitionIndctr ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocEmphasisDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n      hi pandocEmphasisNestedDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisNestedDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisEmphasisDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrikeoutDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi pandocVerbatimInlineDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocSuperscriptDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocSubscriptDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocTableStructure ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi! link pandocTableStructureTop pandocTableStructre\n      hi! link pandocTableStructureEnd pandocTableStructre\n      hi pandocTableZebraLight ctermfg=32 ctermbg=235 guifg=#268bd2 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n      hi pandocTableZebraDark ctermfg=32 ctermbg=236 guifg=#268bd2 guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n      hi pandocEmphasisTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n      hi pandocEmphasisNestedTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisNestedTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisEmphasisTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrikeoutTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi pandocVerbatimInlineTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocSuperscriptTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocSubscriptTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocHeadingMarker ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocEmphasisHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocEmphasisNestedHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisNestedHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisEmphasisHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrikeoutHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi pandocVerbatimInlineHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocSuperscriptHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocSubscriptHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocLinkDelim ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocLinkLabel ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocLinkText ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocLinkURL ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocLinkTitle ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocLinkTitleDelim ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=#657b83 cterm=NONE gui=NONE\n      hi pandocLinkDefinition ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#657b83 cterm=NONE gui=NONE\n      hi pandocLinkDefinitionID ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocImageCaption ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocFootnoteLink ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocFootnoteDefLink ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocFootnoteInline ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocFootnote ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocCitationDelim ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocCitation ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocCitationID ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocCitationRef ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocStyleDelim ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocEmphasis ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n      hi pandocEmphasisNested ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasis ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisNested ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrongEmphasisEmphasis ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocStrikeout ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi pandocVerbatimInline ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocSuperscript ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocSubscript ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocRule ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocRuleLine ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocEscapePair ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi pandocCitationRef ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocNonBreakingSpace ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n      hi! link pandocEscapedCharacter pandocEscapePair\n      hi! link pandocLineBreak pandocEscapePair\n      hi pandocMetadataDelim ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocMetadata ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocMetadataKey ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n      hi pandocMetadata ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n      hi! link pandocMetadataTitle pandocMetadata\n    endif\n    if get(g:, \"solarized_term_italics\", 0)\n      hi Comment cterm=italic\n      hi gitcommitComment cterm=italic\n      hi htmlSpecialTagName cterm=italic\n      hi pandocComment cterm=italic\n      hi pandocEmphasisDefinition cterm=italic\n      hi pandocEmphasisTable cterm=italic\n      hi pandocEmphasis cterm=italic\n    endif\n    if has('nvim')\n      hi! link TermCursor Cursor\n      hi TermCursorNC ctermfg=235 ctermbg=242 guifg=#002b36 guibg=#586e75 guisp=NONE cterm=NONE gui=NONE\n      let g:terminal_color_8='#002b36'\n      let g:terminal_color_0='#073642'\n      let g:terminal_color_10='#586e75'\n      let g:terminal_color_11='#657b83'\n      let g:terminal_color_12='#839496'\n      let g:terminal_color_14='#93a1a1'\n      let g:terminal_color_7='#eee8d5'\n      let g:terminal_color_15='#fdf6e3'\n      let g:terminal_color_3='#b58900'\n      let g:terminal_color_9='#cb4b16'\n      let g:terminal_color_1='#dc322f'\n      let g:terminal_color_5='#d33682'\n      let g:terminal_color_13='#6c71c4'\n      let g:terminal_color_4='#268bd2'\n      let g:terminal_color_6='#2aa198'\n      let g:terminal_color_2='#859900'\n    endif\n    finish\n  endif\n\n  \" Color similarity table (light background)\n  \"  yellow: GUI=#b58900/rgb(181,137,  0)  Term=136 #af8700/rgb(175,135,  0)  [delta=1.465279]\n  \"    blue: GUI=#268bd2/rgb( 38,139,210)  Term= 32 #0087d7/rgb(  0,135,215)  [delta=2.677029]\n  \" magenta: GUI=#d33682/rgb(211, 54,130)  Term=162 #d70087/rgb(215,  0,135)  [delta=4.342643]\n  \"    cyan: GUI=#2aa198/rgb( 42,161,152)  Term= 37 #00afaf/rgb(  0,175,175)  [delta=5.365780]\n  \"  base01: GUI=#93a1a1/rgb(147,161,161)  Term=247 #9e9e9e/rgb(158,158,158)  [delta=6.489730]\n  \"  violet: GUI=#6c71c4/rgb(108,113,196)  Term= 61 #5f5faf/rgb( 95, 95,175)  [delta=6.795109]\n  \"     red: GUI=#dc322f/rgb(220, 50, 47)  Term=160 #d70000/rgb(215,  0,  0)  [delta=6.843619]\n  \"   green: GUI=#859900/rgb(133,153,  0)  Term=106 #87af00/rgb(135,175,  0)  [delta=6.901386]\n  \"  base00: GUI=#839496/rgb(131,148,150)  Term=246 #949494/rgb(148,148,148)  [delta=7.557606]\n  \"    back: GUI=#fdf6e3/rgb(253,246,227)  Term=230 #ffffd7/rgb(255,255,215)  [delta=7.816259]\n  \"  base03: GUI=#fdf6e3/rgb(253,246,227)  Term=230 #ffffd7/rgb(255,255,215)  [delta=7.816259]\n  \"  orange: GUI=#cb4b16/rgb(203, 75, 22)  Term=166 #d75f00/rgb(215, 95,  0)  [delta=8.065025]\n  \"  base02: GUI=#eee8d5/rgb(238,232,213)  Term=254 #e4e4e4/rgb(228,228,228)  [delta=8.289679]\n  \"   base0: GUI=#657b83/rgb(101,123,131)  Term= 66 #5f8787/rgb( 95,135,135)  [delta=8.468738]\n  \"   base1: GUI=#586e75/rgb( 88,110,117)  Term=242 #6c6c6c/rgb(108,108,108)  [delta=9.227744]\n  \"   base3: GUI=#002b36/rgb(  0, 43, 54)  Term=235 #262626/rgb( 38, 38, 38)  [delta=12.727247]\n  \"   base2: GUI=#073642/rgb(  7, 54, 66)  Term=236 #303030/rgb( 48, 48, 48)  [delta=13.434724]\n  if !has('gui_running') && get(g:, 'solarized_termtrans', 0)\n    hi Normal ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi FoldColumn ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi Folded ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=#fdf6e3 cterm=NONE,bold gui=NONE,bold\n    hi LineNr ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi Terminal ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi CursorLineNr ctermbg=NONE guifg=NONE\n  else\n    hi Normal ctermfg=66 ctermbg=230 guifg=#657b83 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi FoldColumn ctermfg=66 ctermbg=254 guifg=#657b83 guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n    hi Folded ctermfg=66 ctermbg=254 guifg=#657b83 guibg=#eee8d5 guisp=#fdf6e3 cterm=NONE,bold gui=NONE,bold\n    hi LineNr ctermfg=247 ctermbg=254 guifg=#93a1a1 guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n    hi Terminal ctermfg=fg ctermbg=230 guifg=fg guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi CursorLineNr ctermbg=254 guibg=#eee8d5\n  endif\n  if get(g:, \"solarized_visibility\", \"\") == \"high\"\n    hi CursorLineNr ctermfg=160 guifg=#dc322f cterm=bold gui=bold\n    if get(g:, 'solarized_old_cursor_style', 0)\n      hi Cursor ctermfg=230 ctermbg=66 guifg=#fdf6e3 guibg=#657b83 guisp=NONE cterm=NONE gui=NONE\n    else\n      hi Cursor ctermfg=230 ctermbg=160 guifg=#fdf6e3 guibg=#dc322f guisp=NONE cterm=NONE gui=NONE\n    endif\n    hi MatchParen ctermfg=230 ctermbg=246 guifg=#fdf6e3 guibg=#839496 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi NonText ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpecialKey ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi SpellBad ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=#6c71c4 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi SpellCap ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=#6c71c4 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi SpellLocal ctermfg=136 ctermbg=230 guifg=#b58900 guibg=#fdf6e3 guisp=#cb4b16 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi SpellRare ctermfg=37 ctermbg=230 guifg=#2aa198 guibg=#fdf6e3 guisp=#cb4b16 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi Title ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  elseif get(g:, \"solarized_visibility\", \"\") == \"low\"\n    hi CursorLineNr ctermfg=247 guifg=#93a1a1 cterm=bold gui=bold\n    if get(g:, 'solarized_old_cursor_style', 0)\n      hi Cursor ctermfg=230 ctermbg=66 guifg=#fdf6e3 guibg=#657b83 guisp=NONE cterm=NONE gui=NONE\n    else\n      hi Cursor ctermfg=230 ctermbg=166 guifg=#fdf6e3 guibg=#cb4b16 guisp=NONE cterm=NONE gui=NONE\n    endif\n    hi MatchParen ctermfg=160 ctermbg=254 guifg=#dc322f guibg=#eee8d5 guisp=NONE cterm=NONE,bold,underline gui=NONE,bold,underline\n    hi NonText ctermfg=254 ctermbg=NONE guifg=#eee8d5 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpecialKey ctermfg=254 ctermbg=NONE guifg=#eee8d5 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpellBad ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellCap ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellLocal ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellRare ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n    hi Title ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  else\n    hi CursorLineNr ctermfg=66 guifg=#657b83 cterm=bold gui=bold\n    if get(g:, 'solarized_old_cursor_style', 0)\n      hi Cursor ctermfg=230 ctermbg=66 guifg=#fdf6e3 guibg=#657b83 guisp=NONE cterm=NONE gui=NONE\n    else\n      hi Cursor ctermfg=230 ctermbg=166 guifg=#fdf6e3 guibg=#cb4b16 guisp=NONE cterm=NONE gui=NONE\n    endif\n    hi MatchParen ctermfg=160 ctermbg=254 guifg=#dc322f guibg=#eee8d5 guisp=NONE cterm=NONE,bold,underline gui=NONE,bold,underline\n    hi NonText ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpecialKey ctermfg=246 ctermbg=254 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpellBad ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellCap ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellLocal ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellRare ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n    hi Title ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  endif\n  hi ColorColumn ctermfg=NONE ctermbg=254 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n  hi Conceal ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi CursorColumn ctermfg=NONE ctermbg=254 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n  hi CursorLine ctermfg=NONE ctermbg=254 guifg=NONE guibg=#eee8d5 guisp=#586e75 cterm=NONE gui=NONE\n  if get(g:, \"solarized_diffmode\", \"\") == \"high\"\n    hi DiffAdd ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi DiffChange ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi DiffDelete ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi DiffText ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  elseif get(g:, \"solarized_diffmode\", \"\") == \"low\"\n    hi DiffAdd ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=#859900 cterm=NONE gui=NONE\n    hi DiffChange ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE gui=NONE\n    hi DiffDelete ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi DiffText ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=#268bd2 cterm=NONE gui=NONE\n  else\n    hi DiffAdd ctermfg=106 ctermbg=254 guifg=#859900 guibg=#eee8d5 guisp=#859900 cterm=NONE gui=NONE\n    hi DiffChange ctermfg=136 ctermbg=254 guifg=#b58900 guibg=#eee8d5 guisp=#b58900 cterm=NONE gui=NONE\n    hi DiffDelete ctermfg=160 ctermbg=254 guifg=#dc322f guibg=#eee8d5 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi DiffText ctermfg=32 ctermbg=254 guifg=#268bd2 guibg=#eee8d5 guisp=#268bd2 cterm=NONE gui=NONE\n  endif\n  hi Directory ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi EndOfBuffer ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi ErrorMsg ctermfg=160 ctermbg=230 guifg=#dc322f guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi IncSearch ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n  hi ModeMsg ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi MoreMsg ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi Pmenu ctermfg=66 ctermbg=254 guifg=#657b83 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi PmenuSbar ctermfg=236 ctermbg=66 guifg=#073642 guibg=#657b83 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi PmenuSel ctermfg=247 ctermbg=236 guifg=#93a1a1 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi PmenuThumb ctermfg=66 ctermbg=230 guifg=#657b83 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi Question ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link QuickFixLine Search\n  hi Search ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi SignColumn ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  if get(g:, \"solarized_statusline\", \"\") == \"low\"\n    hi StatusLine ctermfg=247 ctermbg=230 guifg=#93a1a1 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi StatusLineNC ctermfg=247 ctermbg=242 guifg=#93a1a1 guibg=#586e75 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLine ctermfg=247 ctermbg=242 guifg=#93a1a1 guibg=#586e75 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineFill ctermfg=247 ctermbg=242 guifg=#93a1a1 guibg=#586e75 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineSel ctermfg=242 ctermbg=230 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  else\n    hi StatusLine ctermfg=242 ctermbg=254 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi StatusLineNC ctermfg=246 ctermbg=254 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLine ctermfg=246 ctermbg=254 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineFill ctermfg=246 ctermbg=254 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineSel ctermfg=242 ctermbg=254 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  endif\n  hi! link StatusLineTerm StatusLine\n  hi! link StatusLineTermNC StatusLineNC\n  hi VertSplit ctermfg=247 ctermbg=247 guifg=#93a1a1 guibg=#93a1a1 guisp=NONE cterm=NONE gui=NONE\n  hi Visual ctermfg=247 ctermbg=230 guifg=#93a1a1 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi VisualNOS ctermfg=NONE ctermbg=254 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi WarningMsg ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi WildMenu ctermfg=236 ctermbg=254 guifg=#073642 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi! link Boolean Constant\n  hi! link Character Constant\n  hi Comment ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi! link Conditional Statement\n  hi Constant ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Define PreProc\n  hi! link Debug Special\n  hi! link Delimiter Special\n  hi Error ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link Exception Statement\n  hi! link Float Constant\n  hi! link Function Identifier\n  hi Identifier ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi Ignore ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Include PreProc\n  hi! link Keyword Statement\n  hi! link Label Statement\n  hi! link Macro PreProc\n  hi! link Number Constant\n  hi! link Operator Statement\n  hi! link PreCondit PreProc\n  hi PreProc ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Repeat Statement\n  hi Special ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link SpecialChar Special\n  hi! link SpecialComment Special\n  hi Statement ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link StorageClass Type\n  hi! link String Constant\n  hi! link Structure Type\n  hi! link Tag Special\n  hi Todo ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi Type ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Typedef Type\n  hi Underlined ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link lCursor Cursor\n  hi CursorIM ctermfg=NONE ctermbg=fg guifg=NONE guibg=fg guisp=NONE cterm=NONE gui=NONE\n  hi ToolbarLine ctermfg=NONE ctermbg=254 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n  hi ToolbarButton ctermfg=242 ctermbg=254 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi NormalMode ctermfg=242 ctermbg=230 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi InsertMode ctermfg=37 ctermbg=230 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi ReplaceMode ctermfg=166 ctermbg=230 guifg=#cb4b16 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi VisualMode ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi CommandMode ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  if get(g:, 'solarized_extra_hi_groups', 0)\n    hi! link vimVar Identifier\n    hi! link vimFunc Function\n    hi! link vimUserFunc Function\n    hi! link helpSpecial Special\n    hi! link vimSet Normal\n    hi! link vimSetEqual Normal\n    hi vimCommentString ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimCommand ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimCmdSep ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi helpExample ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpOption ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpNote ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpVim ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpHyperTextJump ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpHyperTextEntry ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimIsCommand ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimSynMtchOpt ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimSynType ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimHiLink ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimHiGroup ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimGroup ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link diffAdded Statement\n    hi! link diffLine Identifier\n    hi gitcommitComment ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi! link gitcommitUntracked gitcommitComment\n    hi! link gitcommitDiscarded gitcommitComment\n    hi! link gitcommitSelected gitcommitComment\n    hi gitcommitUnmerged ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitOnBranch ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitBranch ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link gitcommitNoBranch gitcommitBranch\n    hi gitcommitdiscardedtype ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi gitcommitselectedtype ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi gitcommitHeader ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi gitcommitUntrackedFile ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitDiscardedFile ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitSelectedFile ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitUnmergedFile ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitFile ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link gitcommitDiscardedArrow gitcommitDiscardedFile\n    hi! link gitcommitSelectedArrow gitcommitSelectedFile\n    hi! link gitcommitUnmergedArrow gitcommitUnmergedFile\n    hi htmlTag ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi htmlEndTag ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi htmlTagN ctermfg=242 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi htmlTagName ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi htmlSpecialTagName ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi htmlArg ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi javaScript ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi perlHereDoc ctermfg=242 ctermbg=230 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi perlVarPlain ctermfg=136 ctermbg=230 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi perlStatementFileDesc ctermfg=37 ctermbg=230 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi texstatement ctermfg=37 ctermbg=230 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi texmathzonex ctermfg=136 ctermbg=230 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi texmathmatcher ctermfg=136 ctermbg=230 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi texreflabel ctermfg=136 ctermbg=230 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi rubyDefine ctermfg=242 ctermbg=230 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link rubySymbol Type\n    hi rubyBoolean ctermfg=162 ctermbg=230 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    let hs_highlight_boolean=1\n    let hs_highlight_delimiters=1\n    hi cPreCondit ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi VarId ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi ConId ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsImport ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsString ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsStructure ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hs_hlFunctionName ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsStatement ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsImportLabel ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hs_OpFunctionName ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hs_DeclareFunction ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsVarSym ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsType ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsTypedef ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsModuleName ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link hsImportParams Delimiter\n    hi! link hsDelimTypeExport Delimiter\n    hi! link hsModuleStartLabel hsStructure\n    hi! link hsModuleWhereLabel hsModuleStartLabel\n    hi hsNiceOperator ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsniceoperator ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTitleBlock ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTitleBlockTitle ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocTitleComment ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocComment ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocVerbatimBlock ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link pandocVerbatimBlockDeep pandocVerbatimBlock\n    hi! link pandocCodeBlock pandocVerbatimBlock\n    hi! link pandocCodeBlockDelim pandocVerbatimBlock\n    hi pandocBlockQuote ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader1 ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader2 ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader3 ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader4 ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader5 ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader6 ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocListMarker ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocListReference ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocDefinitionBlock ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocDefinitionTerm ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n    hi pandocDefinitionIndctr ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEmphasisDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocEmphasisNestedDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNestedDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasisDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeoutDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInlineDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSuperscriptDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSubscriptDefinition ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTableStructure ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link pandocTableStructureTop pandocTableStructre\n    hi! link pandocTableStructureEnd pandocTableStructre\n    hi pandocTableZebraLight ctermfg=32 ctermbg=230 guifg=#268bd2 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n    hi pandocTableZebraDark ctermfg=32 ctermbg=254 guifg=#268bd2 guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n    hi pandocEmphasisTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocEmphasisNestedTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNestedTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasisTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeoutTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInlineTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSuperscriptTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSubscriptTable ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocHeadingMarker ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEmphasisHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEmphasisNestedHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNestedHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasisHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeoutHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInlineHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocSuperscriptHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocSubscriptHeading ctermfg=166 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocLinkDelim ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkLabel ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkText ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkURL ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkTitle ctermfg=246 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkTitleDelim ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=#839496 cterm=NONE gui=NONE\n    hi pandocLinkDefinition ctermfg=37 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#839496 cterm=NONE gui=NONE\n    hi pandocLinkDefinitionID ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocImageCaption ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocFootnoteLink ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocFootnoteDefLink ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocFootnoteInline ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocFootnote ctermfg=106 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitationDelim ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitation ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitationID ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitationRef ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocStyleDelim ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocEmphasis ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocEmphasisNested ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasis ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNested ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasis ctermfg=66 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeout ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInline ctermfg=136 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSuperscript ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSubscript ctermfg=61 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocRule ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocRuleLine ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEscapePair ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocCitationRef ctermfg=162 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocNonBreakingSpace ctermfg=160 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi! link pandocEscapedCharacter pandocEscapePair\n    hi! link pandocLineBreak pandocEscapePair\n    hi pandocMetadataDelim ctermfg=247 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocMetadata ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocMetadataKey ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocMetadata ctermfg=32 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link pandocMetadataTitle pandocMetadata\n  endif\n  if get(g:, \"solarized_term_italics\", 0)\n    hi Comment cterm=italic\n    hi gitcommitComment cterm=italic\n    hi htmlSpecialTagName cterm=italic\n    hi pandocComment cterm=italic\n    hi pandocEmphasisDefinition cterm=italic\n    hi pandocEmphasisTable cterm=italic\n    hi pandocEmphasis cterm=italic\n  endif\n  if has('nvim')\n    hi! link TermCursor Cursor\n    hi TermCursorNC ctermfg=230 ctermbg=247 guifg=#fdf6e3 guibg=#93a1a1 guisp=NONE cterm=NONE gui=NONE\n    let g:terminal_color_8='#fdf6e3'\n    let g:terminal_color_0='#eee8d5'\n    let g:terminal_color_10='#93a1a1'\n    let g:terminal_color_11='#839496'\n    let g:terminal_color_12='#657b83'\n    let g:terminal_color_14='#586e75'\n    let g:terminal_color_7='#073642'\n    let g:terminal_color_15='#002b36'\n    let g:terminal_color_3='#b58900'\n    let g:terminal_color_9='#cb4b16'\n    let g:terminal_color_1='#dc322f'\n    let g:terminal_color_5='#d33682'\n    let g:terminal_color_13='#6c71c4'\n    let g:terminal_color_4='#268bd2'\n    let g:terminal_color_6='#2aa198'\n    let g:terminal_color_2='#859900'\n  endif\n  finish\nendif\n\n\" 16-color variant\nif &background ==# 'dark'\n  if !has('gui_running') && get(g:, 'solarized_termtrans', 0)\n    hi Normal ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi FoldColumn ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi Folded ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=#002b36 cterm=NONE,bold gui=NONE,bold\n    hi LineNr ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi Terminal ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi CursorLineNr ctermbg=NONE guifg=NONE\n  else\n    hi Normal ctermfg=12 ctermbg=8 guifg=#839496 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi FoldColumn ctermfg=12 ctermbg=0 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n    hi Folded ctermfg=12 ctermbg=0 guifg=#839496 guibg=#073642 guisp=#002b36 cterm=NONE,bold gui=NONE,bold\n    hi LineNr ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n    hi Terminal ctermfg=fg ctermbg=8 guifg=fg guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi CursorLineNr ctermbg=0 guibg=#073642\n  endif\n  if get(g:, \"solarized_visibility\", \"\") == \"high\"\n    hi CursorLineNr ctermfg=9 guifg=#cb4b16 cterm=bold gui=bold\n    hi NonText ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpecialKey ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi SpellBad ctermfg=13 ctermbg=15 guifg=#6c71c4 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi SpellCap ctermfg=13 ctermbg=15 guifg=#6c71c4 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi SpellLocal ctermfg=3 ctermbg=15 guifg=#b58900 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi SpellRare ctermfg=6 ctermbg=15 guifg=#2aa198 guibg=#fdf6e3 guisp=#dc322f cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n    hi Title ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  elseif get(g:, \"solarized_visibility\", \"\") == \"low\"\n    hi CursorLineNr ctermfg=10 guifg=#586e75 cterm=bold gui=bold\n    hi NonText ctermfg=0 ctermbg=NONE guifg=#073642 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpecialKey ctermfg=0 ctermbg=NONE guifg=#073642 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi SpellBad ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellCap ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellLocal ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellRare ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n    hi Title ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  else\n    hi CursorLineNr ctermfg=12 guifg=#839496 cterm=bold gui=bold\n    hi NonText ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpecialKey ctermfg=11 ctermbg=0 guifg=#657b83 guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi SpellBad ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellCap ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellLocal ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n    hi SpellRare ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n    hi Title ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  endif\n  hi ColorColumn ctermfg=NONE ctermbg=0 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n  hi Conceal ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  if get(g:, 'solarized_old_cursor_style', 0)\n    hi Cursor ctermfg=8 ctermbg=12 guifg=#002b36 guibg=#839496 guisp=NONE cterm=NONE gui=NONE\n  else\n    hi Cursor ctermfg=15 ctermbg=4 guifg=#fdf6e3 guibg=#268bd2 guisp=NONE cterm=NONE gui=NONE\n  endif\n  hi CursorColumn ctermfg=NONE ctermbg=0 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n  hi CursorLine ctermfg=NONE ctermbg=0 guifg=NONE guibg=#073642 guisp=#93a1a1 cterm=NONE gui=NONE\n  if get(g:, \"solarized_diffmode\", \"\") == \"high\"\n    hi DiffAdd ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi DiffChange ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi DiffDelete ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi DiffText ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  elseif get(g:, \"solarized_diffmode\", \"\") == \"low\"\n    hi DiffAdd ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=#859900 cterm=NONE gui=NONE\n    hi DiffChange ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE gui=NONE\n    hi DiffDelete ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi DiffText ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=#268bd2 cterm=NONE gui=NONE\n  else\n    hi DiffAdd ctermfg=2 ctermbg=0 guifg=#859900 guibg=#073642 guisp=#859900 cterm=NONE gui=NONE\n    hi DiffChange ctermfg=3 ctermbg=0 guifg=#b58900 guibg=#073642 guisp=#b58900 cterm=NONE gui=NONE\n    hi DiffDelete ctermfg=1 ctermbg=0 guifg=#dc322f guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi DiffText ctermfg=4 ctermbg=0 guifg=#268bd2 guibg=#073642 guisp=#268bd2 cterm=NONE gui=NONE\n  endif\n  hi Directory ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi EndOfBuffer ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi ErrorMsg ctermfg=1 ctermbg=15 guifg=#dc322f guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi IncSearch ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n  hi MatchParen ctermfg=15 ctermbg=0 guifg=#fdf6e3 guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi ModeMsg ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi MoreMsg ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi Pmenu ctermfg=12 ctermbg=0 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi PmenuSbar ctermfg=7 ctermbg=12 guifg=#eee8d5 guibg=#839496 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi PmenuSel ctermfg=10 ctermbg=7 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi PmenuThumb ctermfg=12 ctermbg=8 guifg=#839496 guibg=#002b36 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi Question ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link QuickFixLine Search\n  hi Search ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi SignColumn ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  if get(g:, \"solarized_statusline\", \"\") == \"low\"\n    hi StatusLine ctermfg=10 ctermbg=7 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi StatusLineNC ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLine ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineFill ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineSel ctermfg=12 ctermbg=15 guifg=#839496 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  else\n    hi StatusLine ctermfg=12 ctermbg=0 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi StatusLineNC ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLine ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineFill ctermfg=10 ctermbg=0 guifg=#586e75 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi TabLineSel ctermfg=12 ctermbg=0 guifg=#839496 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  endif\n  hi! link StatusLineTerm StatusLine\n  hi! link StatusLineTermNC StatusLineNC\n  hi VertSplit ctermfg=10 ctermbg=10 guifg=#586e75 guibg=#586e75 guisp=NONE cterm=NONE gui=NONE\n  hi Visual ctermfg=10 ctermbg=8 guifg=#586e75 guibg=#002b36 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi VisualNOS ctermfg=NONE ctermbg=0 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi WarningMsg ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi WildMenu ctermfg=7 ctermbg=0 guifg=#eee8d5 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi! link Boolean Constant\n  hi! link Character Constant\n  hi Comment ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi! link Conditional Statement\n  hi Constant ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Define PreProc\n  hi! link Debug Special\n  hi! link Delimiter Special\n  hi Error ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link Exception Statement\n  hi! link Float Constant\n  hi! link Function Identifier\n  hi Identifier ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi Ignore ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Include PreProc\n  hi! link Keyword Statement\n  hi! link Label Statement\n  hi! link Macro PreProc\n  hi! link Number Constant\n  hi! link Operator Statement\n  hi! link PreCondit PreProc\n  hi PreProc ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Repeat Statement\n  hi Special ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link SpecialChar Special\n  hi! link SpecialComment Special\n  hi Statement ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link StorageClass Type\n  hi! link String Constant\n  hi! link Structure Type\n  hi! link Tag Special\n  hi Todo ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi Type ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link Typedef Type\n  hi Underlined ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link lCursor Cursor\n  hi CursorIM ctermfg=NONE ctermbg=fg guifg=NONE guibg=fg guisp=NONE cterm=NONE gui=NONE\n  hi ToolbarLine ctermfg=NONE ctermbg=0 guifg=NONE guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n  hi ToolbarButton ctermfg=14 ctermbg=0 guifg=#93a1a1 guibg=#073642 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi NormalMode ctermfg=12 ctermbg=15 guifg=#839496 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi InsertMode ctermfg=6 ctermbg=15 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi ReplaceMode ctermfg=9 ctermbg=15 guifg=#cb4b16 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi VisualMode ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi CommandMode ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  if get(g:, 'solarized_extra_hi_groups', 0)\n    hi! link vimVar Identifier\n    hi! link vimFunc Function\n    hi! link vimUserFunc Function\n    hi! link helpSpecial Special\n    hi! link vimSet Normal\n    hi! link vimSetEqual Normal\n    hi vimCommentString ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimCommand ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimCmdSep ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi helpExample ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpOption ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpNote ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpVim ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpHyperTextJump ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi helpHyperTextEntry ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimIsCommand ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimSynMtchOpt ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimSynType ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimHiLink ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimHiGroup ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi vimGroup ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link diffAdded Statement\n    hi! link diffLine Identifier\n    hi gitcommitComment ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi! link gitcommitUntracked gitcommitComment\n    hi! link gitcommitDiscarded gitcommitComment\n    hi! link gitcommitSelected gitcommitComment\n    hi gitcommitUnmerged ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitOnBranch ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitBranch ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link gitcommitNoBranch gitcommitBranch\n    hi gitcommitdiscardedtype ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi gitcommitselectedtype ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi gitcommitHeader ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi gitcommitUntrackedFile ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitDiscardedFile ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitSelectedFile ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitUnmergedFile ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi gitcommitFile ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link gitcommitDiscardedArrow gitcommitDiscardedFile\n    hi! link gitcommitSelectedArrow gitcommitSelectedFile\n    hi! link gitcommitUnmergedArrow gitcommitUnmergedFile\n    hi htmlTag ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi htmlEndTag ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi htmlTagN ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi htmlTagName ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi htmlSpecialTagName ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi htmlArg ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi javaScript ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi perlHereDoc ctermfg=14 ctermbg=8 guifg=#93a1a1 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi perlVarPlain ctermfg=3 ctermbg=8 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi perlStatementFileDesc ctermfg=6 ctermbg=8 guifg=#2aa198 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi texstatement ctermfg=6 ctermbg=8 guifg=#2aa198 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi texmathzonex ctermfg=3 ctermbg=8 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi texmathmatcher ctermfg=3 ctermbg=8 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi texreflabel ctermfg=3 ctermbg=8 guifg=#b58900 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi rubyDefine ctermfg=14 ctermbg=8 guifg=#93a1a1 guibg=#002b36 guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link rubySymbol Type\n    hi rubyBoolean ctermfg=5 ctermbg=8 guifg=#d33682 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    let hs_highlight_boolean=1\n    let hs_highlight_delimiters=1\n    hi cPreCondit ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi VarId ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi ConId ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsImport ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsString ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsStructure ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hs_hlFunctionName ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsStatement ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsImportLabel ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hs_OpFunctionName ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hs_DeclareFunction ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsVarSym ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsType ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsTypedef ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsModuleName ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link hsImportParams Delimiter\n    hi! link hsDelimTypeExport Delimiter\n    hi! link hsModuleStartLabel hsStructure\n    hi! link hsModuleWhereLabel hsModuleStartLabel\n    hi hsNiceOperator ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi hsniceoperator ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTitleBlock ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTitleBlockTitle ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocTitleComment ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocComment ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocVerbatimBlock ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link pandocVerbatimBlockDeep pandocVerbatimBlock\n    hi! link pandocCodeBlock pandocVerbatimBlock\n    hi! link pandocCodeBlockDelim pandocVerbatimBlock\n    hi pandocBlockQuote ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader1 ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader2 ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader3 ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader4 ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader5 ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocBlockQuoteLeader6 ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocListMarker ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocListReference ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocDefinitionBlock ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocDefinitionTerm ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n    hi pandocDefinitionIndctr ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEmphasisDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocEmphasisNestedDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNestedDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasisDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeoutDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInlineDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSuperscriptDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSubscriptDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocTableStructure ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi! link pandocTableStructureTop pandocTableStructre\n    hi! link pandocTableStructureEnd pandocTableStructre\n    hi pandocTableZebraLight ctermfg=4 ctermbg=8 guifg=#268bd2 guibg=#002b36 guisp=NONE cterm=NONE gui=NONE\n    hi pandocTableZebraDark ctermfg=4 ctermbg=0 guifg=#268bd2 guibg=#073642 guisp=NONE cterm=NONE gui=NONE\n    hi pandocEmphasisTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocEmphasisNestedTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNestedTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasisTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeoutTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInlineTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSuperscriptTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSubscriptTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocHeadingMarker ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEmphasisHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEmphasisNestedHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNestedHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasisHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeoutHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInlineHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocSuperscriptHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocSubscriptHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocLinkDelim ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkLabel ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkText ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkURL ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkTitle ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocLinkTitleDelim ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=#657b83 cterm=NONE gui=NONE\n    hi pandocLinkDefinition ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#657b83 cterm=NONE gui=NONE\n    hi pandocLinkDefinitionID ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocImageCaption ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocFootnoteLink ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocFootnoteDefLink ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocFootnoteInline ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocFootnote ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitationDelim ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitation ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitationID ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocCitationRef ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocStyleDelim ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocEmphasis ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n    hi pandocEmphasisNested ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasis ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisNested ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrongEmphasisEmphasis ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocStrikeout ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi pandocVerbatimInline ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSuperscript ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocSubscript ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocRule ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocRuleLine ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocEscapePair ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi pandocCitationRef ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocNonBreakingSpace ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n    hi! link pandocEscapedCharacter pandocEscapePair\n    hi! link pandocLineBreak pandocEscapePair\n    hi pandocMetadataDelim ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocMetadata ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocMetadataKey ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n    hi pandocMetadata ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n    hi! link pandocMetadataTitle pandocMetadata\n  endif\n  if get(g:, \"solarized_term_italics\", 0)\n    hi Comment cterm=italic\n    hi gitcommitComment cterm=italic\n    hi htmlSpecialTagName cterm=italic\n    hi pandocComment cterm=italic\n    hi pandocEmphasisDefinition cterm=italic\n    hi pandocEmphasisTable cterm=italic\n    hi pandocEmphasis cterm=italic\n  endif\n  if has('nvim')\n    hi! link TermCursor Cursor\n    hi TermCursorNC ctermfg=8 ctermbg=10 guifg=#002b36 guibg=#586e75 guisp=NONE cterm=NONE gui=NONE\n    let g:terminal_color_8='#002b36'\n    let g:terminal_color_0='#073642'\n    let g:terminal_color_10='#586e75'\n    let g:terminal_color_11='#657b83'\n    let g:terminal_color_12='#839496'\n    let g:terminal_color_14='#93a1a1'\n    let g:terminal_color_7='#eee8d5'\n    let g:terminal_color_15='#fdf6e3'\n    let g:terminal_color_3='#b58900'\n    let g:terminal_color_9='#cb4b16'\n    let g:terminal_color_1='#dc322f'\n    let g:terminal_color_5='#d33682'\n    let g:terminal_color_13='#6c71c4'\n    let g:terminal_color_4='#268bd2'\n    let g:terminal_color_6='#2aa198'\n    let g:terminal_color_2='#859900'\n  endif\n  finish\nendif\n\nif !has('gui_running') && get(g:, 'solarized_termtrans', 0)\n  hi Normal ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi FoldColumn ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi Folded ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=#fdf6e3 cterm=NONE,bold gui=NONE,bold\n  hi LineNr ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi Terminal ctermfg=fg ctermbg=NONE guifg=fg guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi CursorLineNr ctermbg=NONE guifg=NONE\nelse\n  hi Normal ctermfg=11 ctermbg=15 guifg=#657b83 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi FoldColumn ctermfg=11 ctermbg=7 guifg=#657b83 guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n  hi Folded ctermfg=11 ctermbg=7 guifg=#657b83 guibg=#eee8d5 guisp=#fdf6e3 cterm=NONE,bold gui=NONE,bold\n  hi LineNr ctermfg=14 ctermbg=7 guifg=#93a1a1 guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n  hi Terminal ctermfg=fg ctermbg=15 guifg=fg guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi CursorLineNr ctermbg=7 guibg=#eee8d5\nendif\nif get(g:, \"solarized_visibility\", \"\") == \"high\"\n  hi CursorLineNr ctermfg=1 guifg=#dc322f cterm=bold gui=bold\n  if get(g:, 'solarized_old_cursor_style', 0)\n    hi Cursor ctermfg=15 ctermbg=11 guifg=#fdf6e3 guibg=#657b83 guisp=NONE cterm=NONE gui=NONE\n  else\n    hi Cursor ctermfg=15 ctermbg=1 guifg=#fdf6e3 guibg=#dc322f guisp=NONE cterm=NONE gui=NONE\n  endif\n  hi MatchParen ctermfg=15 ctermbg=12 guifg=#fdf6e3 guibg=#839496 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi NonText ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi SpecialKey ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi SpellBad ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=#6c71c4 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n  hi SpellCap ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=#6c71c4 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n  hi SpellLocal ctermfg=3 ctermbg=15 guifg=#b58900 guibg=#fdf6e3 guisp=#cb4b16 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n  hi SpellRare ctermfg=6 ctermbg=15 guifg=#2aa198 guibg=#fdf6e3 guisp=#cb4b16 cterm=NONE,reverse,underline gui=NONE,reverse,undercurl\n  hi Title ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nelseif get(g:, \"solarized_visibility\", \"\") == \"low\"\n  hi CursorLineNr ctermfg=14 guifg=#93a1a1 cterm=bold gui=bold\n  if get(g:, 'solarized_old_cursor_style', 0)\n    hi Cursor ctermfg=15 ctermbg=11 guifg=#fdf6e3 guibg=#657b83 guisp=NONE cterm=NONE gui=NONE\n  else\n    hi Cursor ctermfg=15 ctermbg=9 guifg=#fdf6e3 guibg=#cb4b16 guisp=NONE cterm=NONE gui=NONE\n  endif\n  hi MatchParen ctermfg=1 ctermbg=7 guifg=#dc322f guibg=#eee8d5 guisp=NONE cterm=NONE,bold,underline gui=NONE,bold,underline\n  hi NonText ctermfg=7 ctermbg=NONE guifg=#eee8d5 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi SpecialKey ctermfg=7 ctermbg=NONE guifg=#eee8d5 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi SpellBad ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n  hi SpellCap ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n  hi SpellLocal ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n  hi SpellRare ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n  hi Title ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nelse\n  hi CursorLineNr ctermfg=11 guifg=#657b83 cterm=bold gui=bold\n  if get(g:, 'solarized_old_cursor_style', 0)\n    hi Cursor ctermfg=15 ctermbg=11 guifg=#fdf6e3 guibg=#657b83 guisp=NONE cterm=NONE gui=NONE\n  else\n    hi Cursor ctermfg=15 ctermbg=9 guifg=#fdf6e3 guibg=#cb4b16 guisp=NONE cterm=NONE gui=NONE\n  endif\n  hi MatchParen ctermfg=1 ctermbg=7 guifg=#dc322f guibg=#eee8d5 guisp=NONE cterm=NONE,bold,underline gui=NONE,bold,underline\n  hi NonText ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi SpecialKey ctermfg=12 ctermbg=7 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi SpellBad ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n  hi SpellCap ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=#6c71c4 cterm=NONE,underline gui=NONE,undercurl\n  hi SpellLocal ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE,underline gui=NONE,undercurl\n  hi SpellRare ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#2aa198 cterm=NONE,underline gui=NONE,undercurl\n  hi Title ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nendif\nhi ColorColumn ctermfg=NONE ctermbg=7 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\nhi Conceal ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi CursorColumn ctermfg=NONE ctermbg=7 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\nhi CursorLine ctermfg=NONE ctermbg=7 guifg=NONE guibg=#eee8d5 guisp=#586e75 cterm=NONE gui=NONE\nif get(g:, \"solarized_diffmode\", \"\") == \"high\"\n  hi DiffAdd ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi DiffChange ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi DiffDelete ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi DiffText ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nelseif get(g:, \"solarized_diffmode\", \"\") == \"low\"\n  hi DiffAdd ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=#859900 cterm=NONE gui=NONE\n  hi DiffChange ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=#b58900 cterm=NONE gui=NONE\n  hi DiffDelete ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi DiffText ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=#268bd2 cterm=NONE gui=NONE\nelse\n  hi DiffAdd ctermfg=2 ctermbg=7 guifg=#859900 guibg=#eee8d5 guisp=#859900 cterm=NONE gui=NONE\n  hi DiffChange ctermfg=3 ctermbg=7 guifg=#b58900 guibg=#eee8d5 guisp=#b58900 cterm=NONE gui=NONE\n  hi DiffDelete ctermfg=1 ctermbg=7 guifg=#dc322f guibg=#eee8d5 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi DiffText ctermfg=4 ctermbg=7 guifg=#268bd2 guibg=#eee8d5 guisp=#268bd2 cterm=NONE gui=NONE\nendif\nhi Directory ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi EndOfBuffer ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi ErrorMsg ctermfg=1 ctermbg=15 guifg=#dc322f guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi IncSearch ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\nhi ModeMsg ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi MoreMsg ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi Pmenu ctermfg=11 ctermbg=7 guifg=#657b83 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi PmenuSbar ctermfg=0 ctermbg=11 guifg=#073642 guibg=#657b83 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi PmenuSel ctermfg=14 ctermbg=0 guifg=#93a1a1 guibg=#073642 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi PmenuThumb ctermfg=11 ctermbg=15 guifg=#657b83 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi Question ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nhi! link QuickFixLine Search\nhi Search ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi SignColumn ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nif get(g:, \"solarized_statusline\", \"\") == \"low\"\n  hi StatusLine ctermfg=14 ctermbg=15 guifg=#93a1a1 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi StatusLineNC ctermfg=14 ctermbg=10 guifg=#93a1a1 guibg=#586e75 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi TabLine ctermfg=14 ctermbg=10 guifg=#93a1a1 guibg=#586e75 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi TabLineFill ctermfg=14 ctermbg=10 guifg=#93a1a1 guibg=#586e75 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi TabLineSel ctermfg=10 ctermbg=15 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nelse\n  hi StatusLine ctermfg=10 ctermbg=7 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi StatusLineNC ctermfg=12 ctermbg=7 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi TabLine ctermfg=12 ctermbg=7 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi TabLineFill ctermfg=12 ctermbg=7 guifg=#839496 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi TabLineSel ctermfg=10 ctermbg=7 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nendif\nhi! link StatusLineTerm StatusLine\nhi! link StatusLineTermNC StatusLineNC\nhi VertSplit ctermfg=14 ctermbg=14 guifg=#93a1a1 guibg=#93a1a1 guisp=NONE cterm=NONE gui=NONE\nhi Visual ctermfg=14 ctermbg=15 guifg=#93a1a1 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi VisualNOS ctermfg=NONE ctermbg=7 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi WarningMsg ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nhi WildMenu ctermfg=0 ctermbg=7 guifg=#073642 guibg=#eee8d5 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi! link Boolean Constant\nhi! link Character Constant\nhi Comment ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\nhi! link Conditional Statement\nhi Constant ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link Define PreProc\nhi! link Debug Special\nhi! link Delimiter Special\nhi Error ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nhi! link Exception Statement\nhi! link Float Constant\nhi! link Function Identifier\nhi Identifier ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi Ignore ctermfg=NONE ctermbg=NONE guifg=NONE guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link Include PreProc\nhi! link Keyword Statement\nhi! link Label Statement\nhi! link Macro PreProc\nhi! link Number Constant\nhi! link Operator Statement\nhi! link PreCondit PreProc\nhi PreProc ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link Repeat Statement\nhi Special ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link SpecialChar Special\nhi! link SpecialComment Special\nhi Statement ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link StorageClass Type\nhi! link String Constant\nhi! link Structure Type\nhi! link Tag Special\nhi Todo ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\nhi Type ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link Typedef Type\nhi Underlined ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\nhi! link lCursor Cursor\nhi CursorIM ctermfg=NONE ctermbg=fg guifg=NONE guibg=fg guisp=NONE cterm=NONE gui=NONE\nhi ToolbarLine ctermfg=NONE ctermbg=7 guifg=NONE guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\nhi ToolbarButton ctermfg=10 ctermbg=7 guifg=#586e75 guibg=#eee8d5 guisp=NONE cterm=NONE,bold gui=NONE,bold\nhi NormalMode ctermfg=10 ctermbg=15 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi InsertMode ctermfg=6 ctermbg=15 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi ReplaceMode ctermfg=9 ctermbg=15 guifg=#cb4b16 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi VisualMode ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nhi CommandMode ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE,reverse gui=NONE,reverse\nif get(g:, 'solarized_extra_hi_groups', 0)\n  hi! link vimVar Identifier\n  hi! link vimFunc Function\n  hi! link vimUserFunc Function\n  hi! link helpSpecial Special\n  hi! link vimSet Normal\n  hi! link vimSetEqual Normal\n  hi vimCommentString ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimCommand ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimCmdSep ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi helpExample ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi helpOption ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi helpNote ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi helpVim ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi helpHyperTextJump ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi helpHyperTextEntry ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimIsCommand ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimSynMtchOpt ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimSynType ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimHiLink ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimHiGroup ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi vimGroup ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link diffAdded Statement\n  hi! link diffLine Identifier\n  hi gitcommitComment ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi! link gitcommitUntracked gitcommitComment\n  hi! link gitcommitDiscarded gitcommitComment\n  hi! link gitcommitSelected gitcommitComment\n  hi gitcommitUnmerged ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi gitcommitOnBranch ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi gitcommitBranch ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link gitcommitNoBranch gitcommitBranch\n  hi gitcommitdiscardedtype ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi gitcommitselectedtype ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi gitcommitHeader ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi gitcommitUntrackedFile ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi gitcommitDiscardedFile ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi gitcommitSelectedFile ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi gitcommitUnmergedFile ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi gitcommitFile ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link gitcommitDiscardedArrow gitcommitDiscardedFile\n  hi! link gitcommitSelectedArrow gitcommitSelectedFile\n  hi! link gitcommitUnmergedArrow gitcommitUnmergedFile\n  hi htmlTag ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi htmlEndTag ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi htmlTagN ctermfg=10 ctermbg=NONE guifg=#586e75 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi htmlTagName ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi htmlSpecialTagName ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi htmlArg ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi javaScript ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi perlHereDoc ctermfg=10 ctermbg=15 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi perlVarPlain ctermfg=3 ctermbg=15 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi perlStatementFileDesc ctermfg=6 ctermbg=15 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi texstatement ctermfg=6 ctermbg=15 guifg=#2aa198 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi texmathzonex ctermfg=3 ctermbg=15 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi texmathmatcher ctermfg=3 ctermbg=15 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi texreflabel ctermfg=3 ctermbg=15 guifg=#b58900 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi rubyDefine ctermfg=10 ctermbg=15 guifg=#586e75 guibg=#fdf6e3 guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link rubySymbol Type\n  hi rubyBoolean ctermfg=5 ctermbg=15 guifg=#d33682 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  let hs_highlight_boolean=1\n  let hs_highlight_delimiters=1\n  hi cPreCondit ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi VarId ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi ConId ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsImport ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsString ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsStructure ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hs_hlFunctionName ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsStatement ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsImportLabel ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hs_OpFunctionName ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hs_DeclareFunction ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsVarSym ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsType ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsTypedef ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsModuleName ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link hsImportParams Delimiter\n  hi! link hsDelimTypeExport Delimiter\n  hi! link hsModuleStartLabel hsStructure\n  hi! link hsModuleWhereLabel hsModuleStartLabel\n  hi hsNiceOperator ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi hsniceoperator ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocTitleBlock ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocTitleBlockTitle ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocTitleComment ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocComment ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi pandocVerbatimBlock ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link pandocVerbatimBlockDeep pandocVerbatimBlock\n  hi! link pandocCodeBlock pandocVerbatimBlock\n  hi! link pandocCodeBlockDelim pandocVerbatimBlock\n  hi pandocBlockQuote ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocBlockQuoteLeader1 ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocBlockQuoteLeader2 ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocBlockQuoteLeader3 ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocBlockQuoteLeader4 ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocBlockQuoteLeader5 ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocBlockQuoteLeader6 ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocListMarker ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocListReference ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocDefinitionBlock ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocDefinitionTerm ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,standout gui=NONE,standout\n  hi pandocDefinitionIndctr ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocEmphasisDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi pandocEmphasisNestedDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisNestedDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisEmphasisDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrikeoutDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi pandocVerbatimInlineDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocSuperscriptDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocSubscriptDefinition ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocTableStructure ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi! link pandocTableStructureTop pandocTableStructre\n  hi! link pandocTableStructureEnd pandocTableStructre\n  hi pandocTableZebraLight ctermfg=4 ctermbg=15 guifg=#268bd2 guibg=#fdf6e3 guisp=NONE cterm=NONE gui=NONE\n  hi pandocTableZebraDark ctermfg=4 ctermbg=7 guifg=#268bd2 guibg=#eee8d5 guisp=NONE cterm=NONE gui=NONE\n  hi pandocEmphasisTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi pandocEmphasisNestedTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisNestedTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisEmphasisTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrikeoutTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi pandocVerbatimInlineTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocSuperscriptTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocSubscriptTable ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocHeadingMarker ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocEmphasisHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocEmphasisNestedHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisNestedHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisEmphasisHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrikeoutHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi pandocVerbatimInlineHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocSuperscriptHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocSubscriptHeading ctermfg=9 ctermbg=NONE guifg=#cb4b16 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocLinkDelim ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocLinkLabel ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocLinkText ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocLinkURL ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocLinkTitle ctermfg=12 ctermbg=NONE guifg=#839496 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocLinkTitleDelim ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=#839496 cterm=NONE gui=NONE\n  hi pandocLinkDefinition ctermfg=6 ctermbg=NONE guifg=#2aa198 guibg=NONE guisp=#839496 cterm=NONE gui=NONE\n  hi pandocLinkDefinitionID ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocImageCaption ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocFootnoteLink ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocFootnoteDefLink ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocFootnoteInline ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocFootnote ctermfg=2 ctermbg=NONE guifg=#859900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocCitationDelim ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocCitation ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocCitationID ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocCitationRef ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocStyleDelim ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocEmphasis ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE gui=NONE,italic\n  hi pandocEmphasisNested ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasis ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisNested ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrongEmphasisEmphasis ctermfg=11 ctermbg=NONE guifg=#657b83 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocStrikeout ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi pandocVerbatimInline ctermfg=3 ctermbg=NONE guifg=#b58900 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocSuperscript ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocSubscript ctermfg=13 ctermbg=NONE guifg=#6c71c4 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocRule ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocRuleLine ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocEscapePair ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi pandocCitationRef ctermfg=5 ctermbg=NONE guifg=#d33682 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocNonBreakingSpace ctermfg=1 ctermbg=NONE guifg=#dc322f guibg=NONE guisp=NONE cterm=NONE,reverse gui=NONE,reverse\n  hi! link pandocEscapedCharacter pandocEscapePair\n  hi! link pandocLineBreak pandocEscapePair\n  hi pandocMetadataDelim ctermfg=14 ctermbg=NONE guifg=#93a1a1 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocMetadata ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocMetadataKey ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE gui=NONE\n  hi pandocMetadata ctermfg=4 ctermbg=NONE guifg=#268bd2 guibg=NONE guisp=NONE cterm=NONE,bold gui=NONE,bold\n  hi! link pandocMetadataTitle pandocMetadata\nendif\nif get(g:, \"solarized_term_italics\", 0)\n  hi Comment cterm=italic\n  hi gitcommitComment cterm=italic\n  hi htmlSpecialTagName cterm=italic\n  hi pandocComment cterm=italic\n  hi pandocEmphasisDefinition cterm=italic\n  hi pandocEmphasisTable cterm=italic\n  hi pandocEmphasis cterm=italic\nendif\nif has('nvim')\n  hi! link TermCursor Cursor\n  hi TermCursorNC ctermfg=15 ctermbg=14 guifg=#fdf6e3 guibg=#93a1a1 guisp=NONE cterm=NONE gui=NONE\n  let g:terminal_color_8='#fdf6e3'\n  let g:terminal_color_0='#eee8d5'\n  let g:terminal_color_10='#93a1a1'\n  let g:terminal_color_11='#839496'\n  let g:terminal_color_12='#657b83'\n  let g:terminal_color_14='#586e75'\n  let g:terminal_color_7='#073642'\n  let g:terminal_color_15='#002b36'\n  let g:terminal_color_3='#b58900'\n  let g:terminal_color_9='#cb4b16'\n  let g:terminal_color_1='#dc322f'\n  let g:terminal_color_5='#d33682'\n  let g:terminal_color_13='#6c71c4'\n  let g:terminal_color_4='#268bd2'\n  let g:terminal_color_6='#2aa198'\n  let g:terminal_color_2='#859900'\nendif\nfinish\n\n\" Background: dark\n\" Color: base03               #002b36                ~        8\n\" Color: base02               #073642                ~        0\n\" Color: base01               #586e75                ~        10\n\" Color: base00               #657b83                ~        11\n\" Color: base0                #839496                ~        12\n\" Color: base1                #93a1a1                ~        14\n\" Color: base2                #eee8d5                ~        7\n\" Color: base3                #fdf6e3                ~        15\n\" Color: yellow               #b58900                ~        3\n\" Color: orange               #cb4b16                ~        9\n\" Color: red                  #dc322f                ~        1\n\" Color: magenta              #d33682                ~        5\n\" Color: violet               #6c71c4                ~        13\n\" Color: blue                 #268bd2                ~        4\n\" Color: cyan                 #2aa198                ~        6\n\" Color: green                #859900                ~        2\n\" Color: back                 #002b36                ~        8\n\"   Normal             base0             none\n\"   FoldColumn         fg                none\n\"   Folded             fg                none             bold s=base03\n\"   LineNr             base01            none\n\"   Terminal           fg                none\n\"   Normal            base0             back\n\"   FoldColumn        base0             base02\n\"   Folded            base0             base02            bold s=base03\n\"   LineNr            base01            base02\n\"   Terminal          fg                back\n\" NonText              orange            none              bold\n\" SpecialKey           orange            none              reverse\n\" SpellBad             violet            base3             t=underline,reverse g=undercurl,reverse s=red\n\" SpellCap             violet            base3             t=underline,reverse g=undercurl,reverse s=red\n\" SpellLocal           yellow            base3             t=underline,reverse g=undercurl,reverse s=red\n\" SpellRare            cyan              base3             t=underline,reverse g=undercurl,reverse s=red\n\" Title                yellow            none              bold\n\" NonText              base02            none              bold\n\" SpecialKey           base02            none              reverse\n\" SpellBad             violet            none              t=underline g=undercurl s=violet\n\" SpellCap             violet            none              t=underline g=undercurl s=violet\n\" SpellLocal           yellow            none              t=underline g=undercurl s=yellow\n\" SpellRare            cyan              none              t=underline g=undercurl s=cyan\n\" Title                base01            none              bold\n\" NonText              base00            none              bold\n\" SpecialKey           base00            base02            bold\n\" SpellBad             violet            none              t=underline g=undercurl s=violet\n\" SpellCap             violet            none              t=underline g=undercurl s=violet\n\" SpellLocal           yellow            none              t=underline g=undercurl s=yellow\n\" SpellRare            cyan              none              t=underline g=undercurl s=cyan\n\" Title                yellow            none              bold\n\" ColorColumn          none              base02\n\" Conceal              blue              none\n\" Cursor               base03            base0\n\" Cursor               base3             blue\n\" CursorColumn         none              base02\n\" CursorLine           none              base02            s=base1\n\" DiffAdd              green             none              reverse\n\" DiffChange           yellow            none              reverse\n\" DiffDelete           red               none              reverse\n\" DiffText             blue              none              reverse\n\" DiffAdd              green             none              s=green\n\" DiffChange           yellow            none              s=yellow\n\" DiffDelete           red               none              bold\n\" DiffText             blue              none              s=blue\n\" DiffAdd              green             base02            s=green\n\" DiffChange           yellow            base02            s=yellow\n\" DiffDelete           red               base02            bold\n\" DiffText             blue              base02            s=blue\n\" Directory            blue              none\n\" EndOfBuffer          none              none\n\" ErrorMsg             red               base3             reverse\n\" IncSearch            orange            none              standout\n\" MatchParen           base3             base02            bold\n\" ModeMsg              blue              none\n\" MoreMsg              blue              none\n\" Pmenu                base0             base02            reverse\n\" PmenuSbar            base2             base0             reverse\n\" PmenuSel             base01            base2             reverse\n\" PmenuThumb           base0             base03            reverse\n\" Question             cyan              none              bold\n\" QuickFixLine     ->  Search\n\" Search               yellow            none              reverse\n\" SignColumn           base0             none\n\" StatusLine           base01            base2             reverse\n\" StatusLineNC         base01            base02            reverse\n\" TabLine              base01            base02            reverse\n\" TabLineFill          base01            base02            reverse\n\" TabLineSel           base0             base3             reverse\n\" StatusLine           base0             base02            reverse\n\" StatusLineNC         base01            base02            reverse\n\" TabLine              base01            base02            reverse\n\" TabLineFill          base01            base02            reverse\n\" TabLineSel           base0             base02            reverse\n\" StatusLineTerm    -> StatusLine\n\" StatusLineTermNC  -> StatusLineNC\n\" VertSplit            base01            base01\n\" Visual               base01            base03            reverse\n\" VisualNOS            none              base02            reverse\n\" WarningMsg           orange            none              bold\n\" WildMenu             base2             base02            reverse\n\" Boolean           -> Constant\n\" Character         -> Constant\n\" Comment              base01            none              g=italic\n\" Conditional       -> Statement\n\" Constant             cyan              none\n\" Define            -> PreProc\n\" Debug             -> Special\n\" Delimiter         -> Special\n\" Error                red               none              bold\n\" Exception         -> Statement\n\" Float             -> Constant\n\" Function          -> Identifier\n\" Identifier           blue              none\n\" Ignore               none              none\n\" Include           -> PreProc\n\" Keyword           -> Statement\n\" Label             -> Statement\n\" Macro             -> PreProc\n\" Number            -> Constant\n\" Operator          -> Statement\n\" PreCondit         -> PreProc\n\" PreProc              orange            none\n\" Repeat            -> Statement\n\" Special              orange            none\n\" SpecialChar       -> Special\n\" SpecialComment    -> Special\n\" Statement            green             none\n\" StorageClass      -> Type\n\" String            -> Constant\n\" Structure         -> Type\n\" Tag               -> Special\n\" Todo                 magenta           none              bold\n\" Type                 yellow            none\n\" Typedef           -> Type\n\" Underlined           violet            none\n\" lCursor           -> Cursor\n\" CursorIM             none              fg\n\" ToolbarLine          none              base02\n\" ToolbarButton        base1             base02            bold\n\" NormalMode           base0             base3             reverse\n\" InsertMode           cyan              base3             reverse\n\" ReplaceMode          orange            base3             reverse\n\" VisualMode           magenta           base3             reverse\n\" CommandMode          magenta           base3             reverse\n\" vimVar            -> Identifier\n\" vimFunc           -> Function\n\" vimUserFunc       -> Function\n\" helpSpecial       -> Special\n\" vimSet            -> Normal\n\" vimSetEqual       -> Normal\n\" vimCommentString     violet            none\n\" vimCommand           yellow            none\n\" vimCmdSep            blue              none              bold\n\" helpExample          base1             none\n\" helpOption           cyan              none\n\" helpNote             magenta           none\n\" helpVim              magenta           none\n\" helpHyperTextJump    blue              none\n\" helpHyperTextEntry   green             none\n\" vimIsCommand         base00            none\n\" vimSynMtchOpt        yellow            none\n\" vimSynType           cyan              none\n\" vimHiLink            blue              none\n\" vimHiGroup           blue              none\n\" vimGroup             blue              none              bold\n\" diffAdded         -> Statement\n\" diffLine          -> Identifier\n\" gitcommitComment           base01          none              g=italic\n\" gitcommitUntracked      -> gitcommitComment\n\" gitcommitDiscarded      -> gitcommitComment\n\" gitcommitSelected       -> gitcommitComment\n\" gitcommitUnmerged          green           none              bold\n\" gitcommitOnBranch          base01          none              bold\n\" gitcommitBranch            magenta         none              bold\n\" gitcommitNoBranch       -> gitcommitBranch\n\" gitcommitdiscardedtype     red             none\n\" gitcommitselectedtype      green           none\n\" gitcommitHeader            base01          none\n\" gitcommitUntrackedFile     cyan            none              bold\n\" gitcommitDiscardedFile     red             none              bold\n\" gitcommitSelectedFile      green           none              bold\n\" gitcommitUnmergedFile      yellow          none              bold\n\" gitcommitFile              base0           none              bold\n\" gitcommitDiscardedArrow -> gitcommitDiscardedFile\n\" gitcommitSelectedArrow  -> gitcommitSelectedFile\n\" gitcommitUnmergedArrow  -> gitcommitUnmergedFile\n\" htmlTag                    base01          none\n\" htmlEndTag                 base01          none\n\" htmlTagN                   base1           none              bold\n\" htmlTagName                blue            none              bold\n\" htmlSpecialTagName         blue            none              g=italic\n\" htmlArg                    base00          none\n\" javaScript                 yellow          none\n\" perlHereDoc                base1           back\n\" perlVarPlain               yellow          back\n\" perlStatementFileDesc      cyan            back\n\" texstatement               cyan            back\n\" texmathzonex               yellow          back\n\" texmathmatcher             yellow          back\n\" texreflabel                yellow          back\n\" rubyDefine                 base1           back              bold\n\" rubySymbol              -> Type\n\" rubyBoolean                magenta         back\n\" cPreCondit                 orange          none\n\" VarId                      blue            none\n\" ConId                      yellow          none\n\" hsImport                   magenta         none\n\" hsString                   base00          none\n\" hsStructure                cyan            none\n\" hs_hlFunctionName          blue            none\n\" hsStatement                cyan            none\n\" hsImportLabel              cyan            none\n\" hs_OpFunctionName          yellow          none\n\" hs_DeclareFunction         orange          none\n\" hsVarSym                   cyan            none\n\" hsType                     yellow          none\n\" hsTypedef                  cyan            none\n\" hsModuleName               green           none\n\" hsImportParams          -> Delimiter\n\" hsDelimTypeExport       -> Delimiter\n\" hsModuleStartLabel      -> hsStructure\n\" hsModuleWhereLabel      -> hsModuleStartLabel\n\" hsNiceOperator             cyan            none\n\" hsniceoperator             cyan            none\n\" pandocTitleBlock                       blue               none\n\" pandocTitleBlockTitle                  blue               none           bold\n\" pandocTitleComment                     blue               none           bold\n\" pandocComment                          base01             none           g=italic\n\" pandocVerbatimBlock                    yellow             none\n\" pandocVerbatimBlockDeep             -> pandocVerbatimBlock\n\" pandocCodeBlock                     -> pandocVerbatimBlock\n\" pandocCodeBlockDelim                -> pandocVerbatimBlock\n\" pandocBlockQuote                       blue               none\n\" pandocBlockQuoteLeader1                blue               none\n\" pandocBlockQuoteLeader2                cyan               none\n\" pandocBlockQuoteLeader3                yellow             none\n\" pandocBlockQuoteLeader4                red                none\n\" pandocBlockQuoteLeader5                base0              none\n\" pandocBlockQuoteLeader6                base01             none\n\" pandocListMarker                       magenta            none\n\" pandocListReference                    magenta            none\n\" pandocDefinitionBlock                  violet             none\n\" pandocDefinitionTerm                   violet             none           standout\n\" pandocDefinitionIndctr                 violet             none           bold\n\" pandocEmphasisDefinition               violet             none           g=italic\n\" pandocEmphasisNestedDefinition         violet             none           bold\n\" pandocStrongEmphasisDefinition         violet             none           bold\n\" pandocStrongEmphasisNestedDefinition   violet             none           bold\n\" pandocStrongEmphasisEmphasisDefinition violet             none           bold\n\" pandocStrikeoutDefinition              violet             none           reverse\n\" pandocVerbatimInlineDefinition         violet             none\n\" pandocSuperscriptDefinition            violet             none\n\" pandocSubscriptDefinition              violet             none\n\" pandocTable                            blue               none\n\" pandocTableStructure                   blue               none\n\" pandocTableStructureTop             -> pandocTableStructre\n\" pandocTableStructureEnd             -> pandocTableStructre\n\" pandocTableZebraLight                  blue               base03\n\" pandocTableZebraDark                   blue               base02\n\" pandocEmphasisTable                    blue               none           g=italic\n\" pandocEmphasisNestedTable              blue               none           bold\n\" pandocStrongEmphasisTable              blue               none           bold\n\" pandocStrongEmphasisNestedTable        blue               none           bold\n\" pandocStrongEmphasisEmphasisTable      blue               none           bold\n\" pandocStrikeoutTable                   blue               none           reverse\n\" pandocVerbatimInlineTable              blue               none\n\" pandocSuperscriptTable                 blue               none\n\" pandocSubscriptTable                   blue               none\n\" pandocHeading                          orange             none           bold\n\" pandocHeadingMarker                    orange             none           bold\n\" pandocEmphasisHeading                  orange             none           bold\n\" pandocEmphasisNestedHeading            orange             none           bold\n\" pandocStrongEmphasisHeading            orange             none           bold\n\" pandocStrongEmphasisNestedHeading      orange             none           bold\n\" pandocStrongEmphasisEmphasisHeading    orange             none           bold\n\" pandocStrikeoutHeading                 orange             none           reverse\n\" pandocVerbatimInlineHeading            orange             none           bold\n\" pandocSuperscriptHeading               orange             none           bold\n\" pandocSubscriptHeading                 orange             none           bold\n\" pandocLinkDelim                        base01             none\n\" pandocLinkLabel                        blue               none\n\" pandocLinkText                         blue               none\n\" pandocLinkURL                          base00             none\n\" pandocLinkTitle                        base00             none\n\" pandocLinkTitleDelim                   base01             none           s=base00\n\" pandocLinkDefinition                   cyan               none           s=base00\n\" pandocLinkDefinitionID                 blue               none           bold\n\" pandocImageCaption                     violet             none           bold\n\" pandocFootnoteLink                     green              none\n\" pandocFootnoteDefLink                  green              none           bold\n\" pandocFootnoteInline                   green              none           bold\n\" pandocFootnote                         green              none\n\" pandocCitationDelim                    magenta            none\n\" pandocCitation                         magenta            none\n\" pandocCitationID                       magenta            none\n\" pandocCitationRef                      magenta            none\n\" pandocStyleDelim                       base01             none\n\" pandocEmphasis                         base0              none           g=italic\n\" pandocEmphasisNested                   base0              none           bold\n\" pandocStrongEmphasis                   base0              none           bold\n\" pandocStrongEmphasisNested             base0              none           bold\n\" pandocStrongEmphasisEmphasis           base0              none           bold\n\" pandocStrikeout                        base01             none           reverse\n\" pandocVerbatimInline                   yellow             none\n\" pandocSuperscript                      violet             none\n\" pandocSubscript                        violet             none\n\" pandocRule                             blue               none           bold\n\" pandocRuleLine                         blue               none           bold\n\" pandocEscapePair                       red                none           bold\n\" pandocCitationRef                      magenta            none\n\" pandocNonBreakingSpace                 red                none           reverse\n\" pandocEscapedCharacter              -> pandocEscapePair\n\" pandocLineBreak                     -> pandocEscapePair\n\" pandocMetadataDelim                    base01             none\n\" pandocMetadata                         blue               none\n\" pandocMetadataKey                      blue               none\n\" pandocMetadata                         blue               none           bold\n\" pandocMetadataTitle                 -> pandocMetadata\n\" TermCursor        -> Cursor\n\" TermCursorNC         base03            base01\n\" Background: light\n\" Color: base3                #002b36                ~        8\n\" Color: base2                #073642                ~        0\n\" Color: base1                #586e75                ~        10\n\" Color: base0                #657b83                ~        11\n\" Color: base00               #839496                ~        12\n\" Color: base01               #93a1a1                ~        14\n\" Color: base02               #eee8d5                ~        7\n\" Color: base03               #fdf6e3                ~        15\n\" Color: yellow               #b58900                ~        3\n\" Color: orange               #cb4b16                ~        9\n\" Color: red                  #dc322f                ~        1\n\" Color: magenta              #d33682                ~        5\n\" Color: violet               #6c71c4                ~        13\n\" Color: blue                 #268bd2                ~        4\n\" Color: cyan                 #2aa198                ~        6\n\" Color: green                #859900                ~        2\n\" Color: back                 #fdf6e3                ~        15\n\"   Normal             base0             none\n\"   FoldColumn         base0             none\n\"   Folded             base0             none              bold s=base03\n\"   LineNr             base01            none\n\"   Terminal           fg                none\n\"   Normal            base0             back\n\"   FoldColumn        base0             base02\n\"   Folded            base0             base02            bold s=base03\n\"   LineNr            base01            base02\n\"   Terminal          fg                back\n\" Cursor               base03            base0\n\" Cursor               base03            red\n\" MatchParen           base03            base00            bold\n\" NonText              red               none              bold\n\" SpecialKey           red               none              reverse\n\" SpellBad             magenta           base03            t=underline,reverse g=undercurl,reverse s=violet\n\" SpellCap             magenta           base03            t=underline,reverse g=undercurl,reverse s=violet\n\" SpellLocal           yellow            base03            t=underline,reverse g=undercurl,reverse s=orange\n\" SpellRare            cyan              base03            t=underline,reverse g=undercurl,reverse s=orange\n\" Title                orange            none              bold\n\" Cursor               base03            base0\n\" Cursor               base03            orange\n\" MatchParen           red               base02            bold,underline\n\" NonText              base02            none              bold\n\" SpecialKey           base02            none              bold\n\" SpellBad             magenta           none              t=underline g=undercurl s=violet\n\" SpellCap             magenta           none              t=underline g=undercurl s=violet\n\" SpellLocal           yellow            none              t=underline g=undercurl s=yellow\n\" SpellRare            cyan              none              t=underline g=undercurl s=cyan\n\" Title                base01            none              bold\n\" Cursor               base03            base0\n\" Cursor               base03            orange\n\" MatchParen           red               base02            bold,underline\n\" NonText              base00            none              bold\n\" SpecialKey           base00            base02            bold\n\" SpellBad             magenta           none              t=underline g=undercurl s=violet\n\" SpellCap             magenta           none              t=underline g=undercurl s=violet\n\" SpellLocal           yellow            none              t=underline g=undercurl s=yellow\n\" SpellRare            cyan              none              t=underline g=undercurl s=cyan\n\" Title                orange            none              bold\n\" ColorColumn          none              base02\n\" Conceal              blue              none\n\" CursorColumn         none              base02\n\" CursorLine           none              base02            s=base1\n\" DiffAdd              green             none              reverse\n\" DiffChange           yellow            none              reverse\n\" DiffDelete           red               none              reverse\n\" DiffText             blue              none              reverse\n\" DiffAdd              green             none              s=green\n\" DiffChange           yellow            none              s=yellow\n\" DiffDelete           red               none              bold\n\" DiffText             blue              none              s=blue\n\" DiffAdd              green             base02            s=green\n\" DiffChange           yellow            base02            s=yellow\n\" DiffDelete           red               base02            bold\n\" DiffText             blue              base02            s=blue\n\" Directory            blue              none\n\" EndOfBuffer          none              none\n\" ErrorMsg             red               base03            reverse\n\" IncSearch            orange            none              standout\n\" ModeMsg              blue              none\n\" MoreMsg              blue              none\n\" Pmenu                base0             base02            reverse\n\" PmenuSbar            base2             base0             reverse\n\" PmenuSel             base01            base2             reverse\n\" PmenuThumb           base0             base03            reverse\n\" Question             cyan              none              bold\n\" QuickFixLine     ->  Search\n\" Search               yellow            none              reverse\n\" SignColumn           base0             none\n\" StatusLine           base01            base03            reverse\n\" StatusLineNC         base01            base1             reverse\n\" TabLine              base01            base1             reverse\n\" TabLineFill          base01            base1             reverse\n\" TabLineSel           base1             base03            reverse\n\" StatusLine           base1             base02            reverse\n\" StatusLineNC         base00            base02            reverse\n\" TabLine              base00            base02            reverse\n\" TabLineFill          base00            base02            reverse\n\" TabLineSel           base1             base02            reverse\n\" StatusLineTerm    -> StatusLine\n\" StatusLineTermNC  -> StatusLineNC\n\" VertSplit            base01            base01\n\" Visual               base01            base03            reverse\n\" VisualNOS            none              base02            reverse\n\" WarningMsg           orange            none              bold\n\" WildMenu             base2             base02            reverse\n\" Boolean           -> Constant\n\" Character         -> Constant\n\" Comment              base01            none              g=italic\n\" Conditional       -> Statement\n\" Constant             cyan              none\n\" Define            -> PreProc\n\" Debug             -> Special\n\" Delimiter         -> Special\n\" Error                red               none              bold\n\" Exception         -> Statement\n\" Float             -> Constant\n\" Function          -> Identifier\n\" Identifier           blue              none\n\" Ignore               none              none\n\" Include           -> PreProc\n\" Keyword           -> Statement\n\" Label             -> Statement\n\" Macro             -> PreProc\n\" Number            -> Constant\n\" Operator          -> Statement\n\" PreCondit         -> PreProc\n\" PreProc              orange            none\n\" Repeat            -> Statement\n\" Special              orange            none\n\" SpecialChar       -> Special\n\" SpecialComment    -> Special\n\" Statement            green             none\n\" StorageClass      -> Type\n\" String            -> Constant\n\" Structure         -> Type\n\" Tag               -> Special\n\" Todo                 magenta           none              bold\n\" Type                 yellow            none\n\" Typedef           -> Type\n\" Underlined           violet            none\n\" lCursor           -> Cursor\n\" CursorIM             none              fg\n\" ToolbarLine          none              base02\n\" ToolbarButton        base1             base02            bold\n\" NormalMode           base1             base03            reverse\n\" InsertMode           cyan              base03            reverse\n\" ReplaceMode          orange            base03            reverse\n\" VisualMode           magenta           base03            reverse\n\" CommandMode          magenta           base03            reverse\n\" vimVar            -> Identifier\n\" vimFunc           -> Function\n\" vimUserFunc       -> Function\n\" helpSpecial       -> Special\n\" vimSet            -> Normal\n\" vimSetEqual       -> Normal\n\" vimCommentString     violet            none\n\" vimCommand           yellow            none\n\" vimCmdSep            blue              none              bold\n\" helpExample          base1             none\n\" helpOption           cyan              none\n\" helpNote             magenta           none\n\" helpVim              magenta           none\n\" helpHyperTextJump    blue              none\n\" helpHyperTextEntry   green             none\n\" vimIsCommand         base00            none\n\" vimSynMtchOpt        yellow            none\n\" vimSynType           cyan              none\n\" vimHiLink            blue              none\n\" vimHiGroup           blue              none\n\" vimGroup             blue              none              bold\n\" diffAdded         -> Statement\n\" diffLine          -> Identifier\n\" gitcommitComment           base01          none              g=italic\n\" gitcommitUntracked      -> gitcommitComment\n\" gitcommitDiscarded      -> gitcommitComment\n\" gitcommitSelected       -> gitcommitComment\n\" gitcommitUnmerged          green           none              bold\n\" gitcommitOnBranch          base01          none              bold\n\" gitcommitBranch            magenta         none              bold\n\" gitcommitNoBranch       -> gitcommitBranch\n\" gitcommitdiscardedtype     red             none\n\" gitcommitselectedtype      green           none\n\" gitcommitHeader            base01          none\n\" gitcommitUntrackedFile     cyan            none              bold\n\" gitcommitDiscardedFile     red             none              bold\n\" gitcommitSelectedFile      green           none              bold\n\" gitcommitUnmergedFile      yellow          none              bold\n\" gitcommitFile              base0           none              bold\n\" gitcommitDiscardedArrow -> gitcommitDiscardedFile\n\" gitcommitSelectedArrow  -> gitcommitSelectedFile\n\" gitcommitUnmergedArrow  -> gitcommitUnmergedFile\n\" htmlTag                    base01          none\n\" htmlEndTag                 base01          none\n\" htmlTagN                   base1           none              bold\n\" htmlTagName                blue            none              bold\n\" htmlSpecialTagName         blue            none              g=italic\n\" htmlArg                    base00          none\n\" javaScript                 yellow          none\n\" perlHereDoc                base1           back\n\" perlVarPlain               yellow          back\n\" perlStatementFileDesc      cyan            back\n\" texstatement               cyan            back\n\" texmathzonex               yellow          back\n\" texmathmatcher             yellow          back\n\" texreflabel                yellow          back\n\" rubyDefine                 base1           back              bold\n\" rubySymbol              -> Type\n\" rubyBoolean                magenta         back\n\" cPreCondit                 orange          none\n\" VarId                      blue            none\n\" ConId                      yellow          none\n\" hsImport                   magenta         none\n\" hsString                   base00          none\n\" hsStructure                cyan            none\n\" hs_hlFunctionName          blue            none\n\" hsStatement                cyan            none\n\" hsImportLabel              cyan            none\n\" hs_OpFunctionName          yellow          none\n\" hs_DeclareFunction         orange          none\n\" hsVarSym                   cyan            none\n\" hsType                     yellow          none\n\" hsTypedef                  cyan            none\n\" hsModuleName               green           none\n\" hsImportParams          -> Delimiter\n\" hsDelimTypeExport       -> Delimiter\n\" hsModuleStartLabel      -> hsStructure\n\" hsModuleWhereLabel      -> hsModuleStartLabel\n\" hsNiceOperator             cyan            none\n\" hsniceoperator             cyan            none\n\" pandocTitleBlock                       blue               none\n\" pandocTitleBlockTitle                  blue               none           bold\n\" pandocTitleComment                     blue               none           bold\n\" pandocComment                          base01             none           g=italic\n\" pandocVerbatimBlock                    yellow             none\n\" pandocVerbatimBlockDeep             -> pandocVerbatimBlock\n\" pandocCodeBlock                     -> pandocVerbatimBlock\n\" pandocCodeBlockDelim                -> pandocVerbatimBlock\n\" pandocBlockQuote                       blue               none\n\" pandocBlockQuoteLeader1                blue               none\n\" pandocBlockQuoteLeader2                cyan               none\n\" pandocBlockQuoteLeader3                yellow             none\n\" pandocBlockQuoteLeader4                red                none\n\" pandocBlockQuoteLeader5                base0              none\n\" pandocBlockQuoteLeader6                base01             none\n\" pandocListMarker                       magenta            none\n\" pandocListReference                    magenta            none\n\" pandocDefinitionBlock                  violet             none\n\" pandocDefinitionTerm                   violet             none           standout\n\" pandocDefinitionIndctr                 violet             none           bold\n\" pandocEmphasisDefinition               violet             none           g=italic\n\" pandocEmphasisNestedDefinition         violet             none           bold\n\" pandocStrongEmphasisDefinition         violet             none           bold\n\" pandocStrongEmphasisNestedDefinition   violet             none           bold\n\" pandocStrongEmphasisEmphasisDefinition violet             none           bold\n\" pandocStrikeoutDefinition              violet             none           reverse\n\" pandocVerbatimInlineDefinition         violet             none\n\" pandocSuperscriptDefinition            violet             none\n\" pandocSubscriptDefinition              violet             none\n\" pandocTable                            blue               none\n\" pandocTableStructure                   blue               none\n\" pandocTableStructureTop             -> pandocTableStructre\n\" pandocTableStructureEnd             -> pandocTableStructre\n\" pandocTableZebraLight                  blue               base03\n\" pandocTableZebraDark                   blue               base02\n\" pandocEmphasisTable                    blue               none           g=italic\n\" pandocEmphasisNestedTable              blue               none           bold\n\" pandocStrongEmphasisTable              blue               none           bold\n\" pandocStrongEmphasisNestedTable        blue               none           bold\n\" pandocStrongEmphasisEmphasisTable      blue               none           bold\n\" pandocStrikeoutTable                   blue               none           reverse\n\" pandocVerbatimInlineTable              blue               none\n\" pandocSuperscriptTable                 blue               none\n\" pandocSubscriptTable                   blue               none\n\" pandocHeading                          orange             none           bold\n\" pandocHeadingMarker                    orange             none           bold\n\" pandocEmphasisHeading                  orange             none           bold\n\" pandocEmphasisNestedHeading            orange             none           bold\n\" pandocStrongEmphasisHeading            orange             none           bold\n\" pandocStrongEmphasisNestedHeading      orange             none           bold\n\" pandocStrongEmphasisEmphasisHeading    orange             none           bold\n\" pandocStrikeoutHeading                 orange             none           reverse\n\" pandocVerbatimInlineHeading            orange             none           bold\n\" pandocSuperscriptHeading               orange             none           bold\n\" pandocSubscriptHeading                 orange             none           bold\n\" pandocLinkDelim                        base01             none\n\" pandocLinkLabel                        blue               none\n\" pandocLinkText                         blue               none\n\" pandocLinkURL                          base00             none\n\" pandocLinkTitle                        base00             none\n\" pandocLinkTitleDelim                   base01             none           s=base00\n\" pandocLinkDefinition                   cyan               none           s=base00\n\" pandocLinkDefinitionID                 blue               none           bold\n\" pandocImageCaption                     violet             none           bold\n\" pandocFootnoteLink                     green              none\n\" pandocFootnoteDefLink                  green              none           bold\n\" pandocFootnoteInline                   green              none           bold\n\" pandocFootnote                         green              none\n\" pandocCitationDelim                    magenta            none\n\" pandocCitation                         magenta            none\n\" pandocCitationID                       magenta            none\n\" pandocCitationRef                      magenta            none\n\" pandocStyleDelim                       base01             none\n\" pandocEmphasis                         base0              none           g=italic\n\" pandocEmphasisNested                   base0              none           bold\n\" pandocStrongEmphasis                   base0              none           bold\n\" pandocStrongEmphasisNested             base0              none           bold\n\" pandocStrongEmphasisEmphasis           base0              none           bold\n\" pandocStrikeout                        base01             none           reverse\n\" pandocVerbatimInline                   yellow             none\n\" pandocSuperscript                      violet             none\n\" pandocSubscript                        violet             none\n\" pandocRule                             blue               none           bold\n\" pandocRuleLine                         blue               none           bold\n\" pandocEscapePair                       red                none           bold\n\" pandocCitationRef                      magenta            none\n\" pandocNonBreakingSpace                 red                none           reverse\n\" pandocEscapedCharacter              -> pandocEscapePair\n\" pandocLineBreak                     -> pandocEscapePair\n\" pandocMetadataDelim                    base01             none\n\" pandocMetadata                         blue               none\n\" pandocMetadataKey                      blue               none\n\" pandocMetadata                         blue               none           bold\n\" pandocMetadataTitle                 -> pandocMetadata\n\" TermCursor        -> Cursor\n\" TermCursorNC         base03            base01\n\n"
  },
  {
    "path": "extensions/theme-solarized/colors/solarized8_dark.json",
    "content": "{\n    \"name\": \"solarized8_dark\",\n    \"baseVimTheme\": \"solarized8\",\n    \"baseVimBackground\": \"dark\",\n    \"colors\": {\n        \"background\": \"#073642\",\n        \"foreground\": \"#839496\",\n\n        \"title.background\": \"#002b36\",\n        \"title.foreground\": \"#839496\",\n\n        \"editor.background\": \"#073642\",\n        \"editor.foreground\": \"#586e75\",\n\n        \"tabs.background\": \"#073642\",\n        \"tabs.foreground\": \"#839496\",\n\n        \"toolTip.background\": \"#002b36\",\n        \"toolTip.foreground\": \"#839496\",\n        \"toolTip.border\": \"#505050\",\n\n        \"menu.background\": \"#002b36\",\n        \"menu.foreground\": \"#839496\",\n        \"menu.border\": \"#505050\",\n\n        \"contextMenu.background\": \"#002b36\",\n        \"contextMenu.foreground\": \"#839496\",\n        \"contextMenu.border\": \"#505050\",\n        \"contextMenu.highlight\": \"#3F4652\",\n\n        \"statusBar.background\": \"#073642\",\n        \"statusBar.foreground\": \"#839496\",\n\n        \"highlight.mode.insert.background\": \"#2aa198\",\n        \"highlight.mode.insert.foreground\": \"#fdf6e3\",\n\n        \"highlight.mode.normal.background\": \"#839496\",\n        \"highlight.mode.normal.foreground\": \"#fdf6e3\",\n\n        \"highlight.mode.operator.background\": \"#d19a66\",\n        \"highlight.mode.operator.foreground\": \"#fdf6e3\",\n\n        \"highlight.mode.visual.background\": \"#d33682\",\n        \"highlight.mode.visual.foreground\": \"#fdf6e3\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-solarized/colors/solarized8_light.json",
    "content": "{\n    \"name\": \"solarized8_light\",\n    \"baseVimTheme\": \"solarized8\",\n    \"baseVimBackground\": \"light\",\n    \"colors\": {\n        \"background\": \"#eee8d5\",\n        \"foreground\": \"#839496\",\n\n        \"title.background\": \"#eee8d5\",\n        \"title.foreground\": \"#839496\",\n\n        \"editor.background\": \"#eee8d5\",\n        \"editor.foreground\": \"#839496\",\n\n        \"tabs.background\": \"#eee8d5\",\n        \"tabs.foreground\": \"#839496\",\n\n        \"toolTip.background\": \"#002b36\",\n        \"toolTip.foreground\": \"#839496\",\n        \"toolTip.border\": \"#505050\",\n\n        \"menu.background\": \"#002b36\",\n        \"menu.foreground\": \"#839496\",\n        \"menu.border\": \"#505050\",\n\n        \"contextMenu.background\": \"#002b36\",\n        \"contextMenu.foreground\": \"#839496\",\n        \"contextMenu.border\": \"#505050\",\n        \"contextMenu.highlight\": \"#3F4652\",\n\n        \"statusBar.background\": \"#839496\",\n        \"statusBar.foreground\": \"#073642\",\n\n        \"highlight.mode.insert.background\": \"#2aa198\",\n        \"highlight.mode.insert.foreground\": \"#fdf6e3\",\n\n        \"highlight.mode.normal.background\": \"#839496\",\n        \"highlight.mode.normal.foreground\": \"#fdf6e3\",\n\n        \"highlight.mode.operator.background\": \"#d19a66\",\n        \"highlight.mode.operator.foreground\": \"#fdf6e3\",\n\n        \"highlight.mode.visual.background\": \"#d33682\",\n        \"highlight.mode.visual.foreground\": \"#fdf6e3\"\n    }\n}\n"
  },
  {
    "path": "extensions/theme-solarized/package.json",
    "content": "{\n    \"name\": \"theme-solarized\",\n    \"version\": \"0.0.1\",\n    \"description\": \"Solarized theme, set for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"themes\": [\n            {\n                \"name\": \"solarized8_dark\",\n                \"path\": \"colors/solarized8_dark.json\"\n            },\n            {\n                \"name\": \"solarized8_light\",\n                \"path\": \"colors/solarized8_light.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/typescript/package.json",
    "content": "{\n    \"name\": \"typescript\",\n    \"version\": \"0.0.1\",\n    \"description\": \"TypeScript extension for Oni\",\n    \"engines\": {\n        \"oni\": \"0.2.18\"\n    },\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"contributes\": {\n        \"snippets\": [\n            {\n                \"language\": \"typescript\",\n                \"path\": \"snippets/typescript.json\"\n            }\n        ]\n    },\n    \"author\": \"\",\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "extensions/typescript/snippets/typescript.json",
    "content": "{\n    \"Constructor\": {\n        \"prefix\": \"ctor\",\n        \"body\": [\"/**\", \" *\", \" */\", \"constructor() {\", \"\\tsuper();\", \"\\t$0\", \"}\"],\n        \"description\": \"Constructor\"\n    },\n    \"Class Definition\": {\n        \"prefix\": \"class\",\n        \"body\": [\"class ${1:name} {\", \"\\tconstructor(${2:parameters}) {\", \"\\t\\t$0\", \"\\t}\", \"}\"],\n        \"description\": \"Class Definition\"\n    },\n    \"Public Method Definition\": {\n        \"prefix\": \"public method\",\n        \"body\": [\"/**\", \" * ${1:name}\", \" */\", \"public ${1:name}() {\", \"\\t$0\", \"}\"],\n        \"description\": \"Public Method Definition\"\n    },\n    \"Private Method Definition\": {\n        \"prefix\": \"private method\",\n        \"body\": [\"private ${1:name}() {\", \"\\t$0\", \"}\"],\n        \"description\": \"Private Method Definition\"\n    },\n    \"Import external module.\": {\n        \"prefix\": \"import statement\",\n        \"body\": [\"import { $0 } from \\\"${1:module}\\\";\"],\n        \"description\": \"Import external module.\"\n    },\n    \"Property getter\": {\n        \"prefix\": \"get\",\n        \"body\": [\"\", \"public get ${1:value}() : ${2:string} {\", \"\\t${3:return $0}\", \"}\", \"\"],\n        \"description\": \"Property getter\"\n    },\n    \"Log to the console\": {\n        \"prefix\": \"log\",\n        \"body\": [\"console.log($1);\", \"$0\"],\n        \"description\": \"Log to the console\"\n    },\n    \"Log warning to console\": {\n        \"prefix\": \"warn\",\n        \"body\": [\"console.warn($1);\", \"$0\"],\n        \"description\": \"Log warning to the console\"\n    },\n    \"Log error to console\": {\n        \"prefix\": \"error\",\n        \"body\": [\"console.error($1);\", \"$0\"],\n        \"description\": \"Log error to the console\"\n    },\n    \"Define a full property\": {\n        \"prefix\": \"prop\",\n        \"body\": [\n            \"\",\n            \"private _${1:value} : ${2:string};\",\n            \"public get ${1:value}() : ${2:string} {\",\n            \"\\treturn this._${1:value};\",\n            \"}\",\n            \"public set ${1:value}(v : ${2:string}) {\",\n            \"\\tthis._${1:value} = v;\",\n            \"}\",\n            \"\"\n        ],\n        \"description\": \"Define a full property\"\n    },\n    \"Triple-slash reference\": {\n        \"prefix\": \"ref\",\n        \"body\": [\"/// <reference path=\\\"$1\\\" />\", \"$0\"],\n        \"description\": \"Triple-slash reference\"\n    },\n    \"Return false\": {\n        \"prefix\": \"ret0\",\n        \"body\": [\"return false;$0\"],\n        \"description\": \"Return false\"\n    },\n    \"Return true\": {\n        \"prefix\": \"ret1\",\n        \"body\": [\"return true;$0\"],\n        \"description\": \"Return true\"\n    },\n    \"Return statement\": {\n        \"prefix\": \"ret\",\n        \"body\": [\"return $1;$0\"],\n        \"description\": \"Return statement\"\n    },\n    \"Property setter\": {\n        \"prefix\": \"set\",\n        \"body\": [\"\", \"public set ${1:value}(v : ${2:string}) {\", \"\\tthis.$3 = v;\", \"}\", \"\"],\n        \"description\": \"Property setter\"\n    },\n    \"Throw Exception\": {\n        \"prefix\": \"throw\",\n        \"body\": [\"throw \\\"$1\\\";\", \"$0\"],\n        \"description\": \"Throw Exception\"\n    },\n    \"For Loop\": {\n        \"prefix\": \"for\",\n        \"body\": [\n            \"for (let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++) {\",\n            \"\\tconst ${3:element} = ${2:array}[${1:index}];\",\n            \"\\t$0\",\n            \"}\"\n        ],\n        \"description\": \"For Loop\"\n    },\n    \"For-Each Loop using =>\": {\n        \"prefix\": \"foreach =>\",\n        \"body\": [\"${1:array}.forEach(${2:element} => {\", \"\\t$0\", \"});\"],\n        \"description\": \"For-Each Loop using =>\"\n    },\n    \"For-In Loop\": {\n        \"prefix\": \"forin\",\n        \"body\": [\n            \"for (const ${1:key} in ${2:object}) {\",\n            \"\\tif (${2:object}.hasOwnProperty(${1:key})) {\",\n            \"\\t\\tconst ${3:element} = ${2:object}[${1:key}];\",\n            \"\\t\\t$0\",\n            \"\\t}\",\n            \"}\"\n        ],\n        \"description\": \"For-In Loop\"\n    },\n    \"For-Of Loop\": {\n        \"prefix\": \"forof\",\n        \"body\": [\"for (const ${1:iterator} of ${2:object}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"For-Of Loop\"\n    },\n    \"Function Statement\": {\n        \"prefix\": \"function\",\n        \"body\": [\"function ${1:name}(${2:params}:${3:type}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"Function Statement\"\n    },\n    \"If Statement\": {\n        \"prefix\": \"if\",\n        \"body\": [\"if (${1:condition}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"If Statement\"\n    },\n    \"If-Else Statement\": {\n        \"prefix\": \"ifelse\",\n        \"body\": [\"if (${1:condition}) {\", \"\\t$0\", \"} else {\", \"\\t\", \"}\"],\n        \"description\": \"If-Else Statement\"\n    },\n    \"New Statement\": {\n        \"prefix\": \"new\",\n        \"body\": [\"const ${1:name} = new ${2:type}(${3:arguments});$0\"],\n        \"description\": \"New Statement\"\n    },\n    \"Switch Statement\": {\n        \"prefix\": \"switch\",\n        \"body\": [\n            \"switch (${1:key}) {\",\n            \"\\tcase ${2:value}:\",\n            \"\\t\\t$0\",\n            \"\\t\\tbreak;\",\n            \"\",\n            \"\\tdefault:\",\n            \"\\t\\tbreak;\",\n            \"}\"\n        ],\n        \"description\": \"Switch Statement\"\n    },\n    \"While Statement\": {\n        \"prefix\": \"while\",\n        \"body\": [\"while (${1:condition}) {\", \"\\t$0\", \"}\"],\n        \"description\": \"While Statement\"\n    },\n    \"Do-While Statement\": {\n        \"prefix\": \"dowhile\",\n        \"body\": [\"do {\", \"\\t$0\", \"} while (${1:condition});\"],\n        \"description\": \"Do-While Statement\"\n    },\n    \"Try-Catch Statement\": {\n        \"prefix\": \"trycatch\",\n        \"body\": [\"try {\", \"\\t$0\", \"} catch (${1:error}) {\", \"\\t\", \"}\"],\n        \"description\": \"Try-Catch Statement\"\n    },\n    \"Set Timeout Function\": {\n        \"prefix\": \"settimeout\",\n        \"body\": [\"setTimeout(() => {\", \"\\t$0\", \"}, ${1:timeout});\"],\n        \"description\": \"Set Timeout Function\"\n    },\n    \"Region Start\": {\n        \"prefix\": \"#region\",\n        \"body\": [\"//#region $0\"],\n        \"description\": \"Folding Region Start\"\n    },\n    \"Region End\": {\n        \"prefix\": \"#endregion\",\n        \"body\": [\"//#endregion\"],\n        \"description\": \"Folding Region End\"\n    }\n}\n"
  },
  {
    "path": "extensions/typescript/syntaxes/TypeScript.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScript.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/Microsoft/TypeScript-TmLanguage/commit/8361b1a232501c67911c81a4664a9460d7922c6b\",\n    \"name\": \"TypeScript\",\n    \"scopeName\": \"source.ts\",\n    \"fileTypes\": [\"ts\"],\n    \"uuid\": \"ef98eb90-bf9b-11e4-bb52-0800200c9a66\",\n    \"patterns\": [\n        {\n            \"include\": \"#directives\"\n        },\n        {\n            \"include\": \"#statements\"\n        },\n        {\n            \"name\": \"comment.line.shebang.ts\",\n            \"match\": \"\\\\A(#!).*(?=$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.ts\"\n                }\n            }\n        }\n    ],\n    \"repository\": {\n        \"statements\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#declaration\"\n                },\n                {\n                    \"include\": \"#control-statement\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#function-declaration\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#interface-declaration\"\n                },\n                {\n                    \"include\": \"#enum-declaration\"\n                },\n                {\n                    \"include\": \"#namespace-declaration\"\n                },\n                {\n                    \"include\": \"#type-alias-declaration\"\n                },\n                {\n                    \"include\": \"#import-equals-declaration\"\n                },\n                {\n                    \"include\": \"#import-declaration\"\n                },\n                {\n                    \"include\": \"#export-declaration\"\n                }\n            ]\n        },\n        \"control-statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#switch-statement\"\n                },\n                {\n                    \"include\": \"#for-loop\"\n                },\n                {\n                    \"name\": \"keyword.control.trycatch.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(catch|finally|throw|try)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.loop.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(break|continue|do|goto|while)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.flow.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(return)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.switch.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(case|default|switch)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.conditional.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(else|if)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.with.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(with)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.other.debugger.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(debugger)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"storage.modifier.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(declare)\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#regex\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#function-expression\"\n                },\n                {\n                    \"include\": \"#class-expression\"\n                },\n                {\n                    \"include\": \"#arrow-function\"\n                },\n                {\n                    \"include\": \"#cast\"\n                },\n                {\n                    \"include\": \"#ternary-expression\"\n                },\n                {\n                    \"include\": \"#new-expr\"\n                },\n                {\n                    \"include\": \"#object-literal\"\n                },\n                {\n                    \"include\": \"#expression-operators\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#literal\"\n                },\n                {\n                    \"include\": \"#support-objects\"\n                },\n                {\n                    \"include\": \"#identifiers\"\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                }\n            ]\n        },\n        \"decorator\": {\n            \"name\": \"meta.decorator.ts\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\@\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.decorator.ts\"\n                }\n            },\n            \"end\": \"(?=\\\\s)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"var-expr\": {\n            \"name\": \"meta.var.expr.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(var|let|const(?!\\\\s+enum\\\\b))\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.ts\"\n                }\n            },\n            \"end\": \"(?=$|^|;|}|(\\\\s+(of|in)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#destructuring-variable\"\n                },\n                {\n                    \"include\": \"#var-single-variable\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(,)\\\\s*(?!\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.comma.ts\"\n                        }\n                    },\n                    \"end\": \"(?<!,)((?==|;|}|(\\\\s+(of|in)\\\\s+)|^\\\\s*$))|((?<=\\\\S)(?=\\\\s*$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#destructuring-variable\"\n                        },\n                        {\n                            \"include\": \"#var-single-variable\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"var-single-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.var-single-variable.expr.ts\",\n                    \"begin\":\n                        \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.ts entity.name.function.ts\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.ts\",\n                    \"begin\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.ts variable.other.constant.ts\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.ts\",\n                    \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.ts variable.other.readwrite.ts\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"var-single-variable-type-annotation\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"destructuring-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.object-binding-pattern-variable.ts\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\{)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.array-binding-pattern-variable.ts\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\[)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"object-binding-element-propertyName\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.destructuring.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"variable.object.property.ts\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-variable-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.ts\"\n                },\n                \"2\": {\n                    \"name\": \"meta.definition.variable.ts variable.other.readwrite.ts\"\n                }\n            }\n        },\n        \"object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.ts\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-binding-element\"\n                }\n            ]\n        },\n        \"array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.ts\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.ts\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-name\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"\\\\s*\\\\b(public|protected|private|readonly)(?=\\\\s+(public|protected|private|readonly)\\\\s+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:(this)|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.ts variable.language.this.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.function.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:((?<!\\\\.|\\\\$)\\\\bthis\\\\b(?!\\\\.|\\\\$))|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.parameter.ts variable.language.this.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"variable.parameter.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.ts\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"destructuring-parameter\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.parameter.object-binding-pattern.ts\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\{)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-object-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.paramter.array-binding-pattern.ts\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\[)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"parameter-object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#parameter-array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-parameter-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.ts\"\n                },\n                \"2\": {\n                    \"name\": \"variable.parameter.ts\"\n                }\n            }\n        },\n        \"parameter-object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.ts\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-object-binding-element\"\n                }\n            ]\n        },\n        \"parameter-array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.ts\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.ts\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"field-declaration\": {\n            \"name\": \"meta.field.declaration.ts\",\n            \"begin\":\n                \"(?<!\\\\()(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s+)?(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.ts\"\n                }\n            },\n            \"end\":\n                \"(?=\\\\}|;|,|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n                    \"end\":\n                        \"(?=[};,=]|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        },\n                        {\n                            \"include\": \"#array-literal\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.ts entity.name.function.ts\",\n                            \"match\":\n                                \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\\\?\\\\s*)?\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.ts variable.object.property.ts\",\n                            \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.optional.ts\",\n                            \"match\": \"\\\\?\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"variable-initializer\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.ts\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[,);}\\\\]])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.ts\"\n                        }\n                    },\n                    \"end\": \"(?=[,);}\\\\]])|(?=^\\\\s*$)|(?<=\\\\S)(?<!=)(?=\\\\s*$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"function-declaration\": {\n            \"name\": \"meta.function.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.async.ts\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.function.ts\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.generator.asterisk.ts\"\n                },\n                \"5\": {\n                    \"name\": \"meta.definition.function.ts entity.name.function.ts\"\n                }\n            },\n            \"end\": \"(?=$|^|;)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-expression\": {\n            \"name\": \"meta.function.expression.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.function.ts\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.ts\"\n                },\n                \"4\": {\n                    \"name\": \"meta.definition.function.ts entity.name.function.ts\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-body\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                },\n                {\n                    \"include\": \"#return-type\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"method-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.method.declaration.ts\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.property.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.generator.asterisk.ts\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.method.declaration.ts\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:(?:\\\\b(?:(new)|(constructor))\\\\b(?!\\\\$|\\\\.|:))|(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))?\\\\s*[\\\\(\\\\<]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.new.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"storage.type.ts\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.generator.asterisk.ts\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-literal-method-declaration\": {\n            \"name\": \"meta.method.declaration.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.property.ts\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.ts\"\n                }\n            },\n            \"end\": \"(?=\\\\}|;|,)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#method-declaration-name\"\n                },\n                {\n                    \"include\": \"#function-body\"\n                },\n                {\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.property.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.generator.asterisk.ts\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\(|\\\\<)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"method-declaration-name\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??)\\\\s*[\\\\(\\\\<])\",\n            \"end\": \"(?=\\\\(|\\\\<)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"meta.definition.method.ts entity.name.function.ts\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                },\n                {\n                    \"name\": \"keyword.operator.optional.ts\",\n                    \"match\": \"\\\\?\"\n                }\n            ]\n        },\n        \"arrow-function\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.arrow.ts\",\n                    \"match\":\n                        \"(?:(?<!\\\\.|\\\\$)(\\\\basync)\\\\s+)?([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?==>)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.parameter.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.arrow.ts\",\n                    \"begin\":\n                        \"(?x) (?:\\n  (?<!\\\\.|\\\\$)(\\\\basync)\\n)? ((?<![})!\\\\]])\\\\s*\\n  (?=\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  )\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.ts\"\n                        }\n                    },\n                    \"end\":\n                        \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameters\"\n                        },\n                        {\n                            \"include\": \"#function-parameters\"\n                        },\n                        {\n                            \"include\": \"#arrow-return-type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.arrow.ts\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.ts\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\}|\\\\S)(?<!=>)|((?!\\\\{)(?=\\\\S))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#decl-block\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"indexer-declaration\": {\n            \"name\": \"meta.indexer.declaration.ts\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.ts\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.ts\"\n                },\n                \"3\": {\n                    \"name\": \"variable.parameter.ts\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.ts\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                }\n            ]\n        },\n        \"indexer-mapped-type-declaration\": {\n            \"name\": \"meta.indexer.mappedtype.declaration.ts\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s+(in)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.ts\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.ts\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.ts\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.operator.expression.in.ts\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.ts\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"function-parameters\": {\n            \"name\": \"meta.parameters.ts\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.begin.ts\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter\"\n                },\n                {\n                    \"include\": \"#parameter-name\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"name\": \"punctuation.separator.parameter.ts\",\n                    \"match\": \",\"\n                }\n            ]\n        },\n        \"class-declaration\": {\n            \"name\": \"meta.class.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(class)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.ts\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.class.ts\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-expression\": {\n            \"name\": \"meta.class.ts\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(class)\\\\b(?=\\\\s+|[<{]|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.class.ts\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-declaration-or-expression-patterns\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.class.ts\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"interface-declaration\": {\n            \"name\": \"meta.interface.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(interface)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.ts\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.interface.ts\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.interface.ts\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"class-or-interface-heritage\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:\\\\b(extends|implements)\\\\b)(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.ts\"\n                }\n            },\n            \"end\": \"(?=\\\\{)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)(?=\\\\s*[_$[:alpha:]][_$[:alnum:]]*(\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)*\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.inherited-class.ts\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"class-or-interface-body\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#access-modifier\"\n                },\n                {\n                    \"include\": \"#property-accessor\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"access-modifier\": {\n            \"name\": \"storage.modifier.ts\",\n            \"match\":\n                \"(?<!\\\\.|\\\\$)\\\\b(abstract|public|protected|private|readonly|static)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"property-accessor\": {\n            \"name\": \"storage.type.property.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(get|set)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"enum-declaration\": {\n            \"name\": \"meta.enum.declaration.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?(?:\\\\b(const)\\\\s+)?\\\\b(enum)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.ts\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.enum.ts\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.type.enum.ts\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"variable.other.enummember.ts\"\n                                }\n                            },\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\":\n                                \"(?=((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\])))\",\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#string\"\n                                },\n                                {\n                                    \"include\": \"#array-literal\"\n                                },\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"namespace-declaration\": {\n            \"name\": \"meta.namespace.declaration.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(namespace|module)\\\\s+(?=[_$[:alpha:]\\\"'`])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.namespace.ts\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\})|(?=;|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"name\": \"entity.name.type.module.ts\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"type-alias-declaration\": {\n            \"name\": \"meta.type.declaration.ts\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(type)\\\\b\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.type.ts\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.alias.ts\"\n                }\n            },\n            \"end\":\n                \"(?=[};]|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"match\": \"(=)\\\\s*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.ts\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"import-equals-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.import-equals.external.ts\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(require)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.control.require.ts\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.brace.round.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.import-equals.internal.ts\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(?!require\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.ts\"\n                        }\n                    },\n                    \"end\": \"(?=;|$|^)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"entity.name.type.module.ts\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.accessor.ts\"\n                                }\n                            }\n                        },\n                        {\n                            \"name\": \"variable.other.readwrite.ts\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-declaration\": {\n            \"name\": \"meta.import.ts\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)(?!(\\\\s*[:\\\\(])|(\\\\$|\\\\.))\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.ts\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.ts\"\n                }\n            },\n            \"end\": \"(?=;|$|^)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-declaration\"\n                }\n            ]\n        },\n        \"export-declaration\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(export)\\\\s+(as)\\\\s+(namespace)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.as.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.namespace.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.module.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.export.default.ts\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?:(?:\\\\s*(=))|(?:\\\\s+(default)(?=\\\\s+)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.assignment.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.default.ts\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.export.ts\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?!(\\\\s*:)|(\\\\$))\\\\b\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.export.ts\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#import-export-declaration\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-export-declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#import-export-block\"\n                },\n                {\n                    \"name\": \"keyword.control.from.ts\",\n                    \"match\": \"\\\\bfrom\\\\b\"\n                },\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-block\": {\n            \"name\": \"meta.block.ts\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-clause\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bdefault)|(\\\\*)|(\\\\b[_$[:alpha:]][_$[:alnum:]]*))\\\\s+(as)\\\\s+(\\\\b[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.default.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.language.import-export-all.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.control.as.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"variable.other.readwrite.alias.ts\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"name\": \"constant.language.import-export-all.ts\",\n                    \"match\": \"\\\\*\"\n                },\n                {\n                    \"name\": \"keyword.control.default.ts\",\n                    \"match\": \"\\\\b(default)\\\\b\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.alias.ts\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"switch-statement\": {\n            \"name\": \"switch-statement.expr.ts\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?=\\\\bswitch\\\\s*\\\\()\",\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"switch-expression.expr.ts\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(switch)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.switch.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.brace.round.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"switch-block.expr.ts\",\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.ts\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"case-clause.expr.ts\",\n                            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(case|default(?=:))\\\\b(?!\\\\$|\\\\.)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.control.switch.ts\"\n                                }\n                            },\n                            \"end\": \":\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.section.case-statement.ts\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#expression\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#statements\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"for-loop\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(for)(?:\\\\s+(await))?\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.ts\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.loop.ts\"\n                },\n                \"3\": {\n                    \"name\": \"meta.brace.round.ts\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"decl-block\": {\n            \"name\": \"meta.block.ts\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#statements\"\n                }\n            ]\n        },\n        \"after-operator-block-as-object-literal\": {\n            \"name\": \"meta.objectliteral.ts\",\n            \"begin\":\n                \"(?<=[=(,\\\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\\\|\\\\||\\\\*)\\\\s*(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-literal\": {\n            \"name\": \"meta.objectliteral.ts\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-member\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-literal-method-declaration\"\n                },\n                {\n                    \"name\": \"meta.object.member.ts meta.object-literal.key.ts\",\n                    \"begin\": \"(?=\\\\[)\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-literal\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.ts meta.object-literal.key.ts\",\n                    \"begin\": \"(?=[\\\\'\\\\\\\"])\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"match\": \"(?![_$[:alpha:]])([[:digit:]]+)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.ts\"\n                        },\n                        \"1\": {\n                            \"name\": \"constant.numeric.decimal.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"match\":\n                        \"(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.ts\"\n                        },\n                        \"1\": {\n                            \"name\": \"entity.name.function.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"match\": \"(?:[_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.ts\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=,|\\\\}|$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.readwrite.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"begin\": \"(?=[_$[:alpha:]][_$[:alnum:]]*\\\\s*=)\",\n                    \"end\": \"(?=,|\\\\}|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.ts\",\n                    \"begin\": \":\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.ts punctuation.separator.key-value.ts\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"ternary-expression\": {\n            \"begin\": \"(\\\\?)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.ts\"\n                }\n            },\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"function-call\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"end\":\n                \"(?<=\\\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.function-call.ts\",\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))\",\n                    \"end\":\n                        \"(?=\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#literal\"\n                        },\n                        {\n                            \"include\": \"#support-objects\"\n                        },\n                        {\n                            \"include\": \"#object-identifiers\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.expression.import.ts\",\n                            \"match\": \"(?![\\\\.\\\\$])\\\\bimport(?=\\\\s*[\\\\(]\\\\s*[\\\\\\\"\\\\'\\\\`])\"\n                        },\n                        {\n                            \"name\": \"entity.name.function.ts\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"meta.type.parameters.ts\",\n                    \"begin\": \"\\\\<\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.begin.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.end.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                }\n            ]\n        },\n        \"new-expr\": {\n            \"name\": \"new.expr.ts\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.new.ts\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\))|(?=[;),}\\\\]]|$|((?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.))|((?<!\\\\.|\\\\$)\\\\bfunction((\\\\s+[_$[:alpha:]][_$[:alnum:]]*)|(\\\\s*[\\\\(]))))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"paren-expression\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.ts\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"cast\": {\n            \"patterns\": [\n                {\n                    \"name\": \"cast.expr.ts\",\n                    \"begin\":\n                        \"(?:(?<=return|throw|yield|await|default|[=(,:>*?]|[^+]\\\\+))\\\\s*(<)(?!<?\\\\=)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.brace.angle.ts\"\n                        }\n                    },\n                    \"end\": \"(\\\\>)\\\\s*\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.brace.angle.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"cast.expr.ts\",\n                    \"begin\": \"(?:(?<=^))\\\\s*(<)(?=[_$[:alpha:]][_$[:alnum:]]*\\\\s*>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.brace.angle.ts\"\n                        }\n                    },\n                    \"end\": \"(\\\\>)\\\\s*\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.brace.angle.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"expression-operators\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.flow.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(await)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(yield)\\\\b(?!\\\\$|\\\\.)(?:\\\\s*(\\\\*))?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.flow.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.generator.asterisk.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"keyword.operator.expression.delete.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bdelete\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.in.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bin\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.of.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.instanceof.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\binstanceof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.new.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.void.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bvoid\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(as)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.as.ts\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,:})\\\\]]|((?<!\\\\.|\\\\$)\\\\b(as)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"keyword.operator.spread.ts\",\n                    \"match\": \"\\\\.\\\\.\\\\.\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.ts\",\n                    \"match\": \"\\\\*=|(?<!\\\\()/=|%=|\\\\+=|\\\\-=\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.bitwise.ts\",\n                    \"match\": \"\\\\&=|\\\\^=|<<=|>>=|>>>=|\\\\|=\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.shift.ts\",\n                    \"match\": \"<<|>>>|>>\"\n                },\n                {\n                    \"name\": \"keyword.operator.comparison.ts\",\n                    \"match\": \"===|!==|==|!=\"\n                },\n                {\n                    \"name\": \"keyword.operator.relational.ts\",\n                    \"match\": \"<=|>=|<>|<|>\"\n                },\n                {\n                    \"name\": \"keyword.operator.logical.ts\",\n                    \"match\": \"\\\\!|&&|\\\\|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.ts\",\n                    \"match\": \"\\\\&|~|\\\\^|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.ts\",\n                    \"match\": \"\\\\=\"\n                },\n                {\n                    \"name\": \"keyword.operator.decrement.ts\",\n                    \"match\": \"--\"\n                },\n                {\n                    \"name\": \"keyword.operator.increment.ts\",\n                    \"match\": \"\\\\+\\\\+\"\n                },\n                {\n                    \"name\": \"keyword.operator.arithmetic.ts\",\n                    \"match\": \"%|\\\\*|/|-|\\\\+\"\n                },\n                {\n                    \"match\": \"(?<=[_$[:alnum:])])\\\\s*(/)(?![/*])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.arithmetic.ts\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"typeof-operator\": {\n            \"name\": \"keyword.operator.expression.typeof.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\btypeof\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#boolean-literal\"\n                },\n                {\n                    \"include\": \"#null-literal\"\n                },\n                {\n                    \"include\": \"#undefined-literal\"\n                },\n                {\n                    \"include\": \"#numericConstant-literal\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"include\": \"#this-literal\"\n                },\n                {\n                    \"include\": \"#super-literal\"\n                }\n            ]\n        },\n        \"array-literal\": {\n            \"name\": \"meta.array.literal.ts\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.ts\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"numeric-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.numeric.hex.ts\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(x|X)[0-9a-fA-F]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.binary.ts\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(b|B)[01]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.octal.ts\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(o|O)?[0-7]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(?<!\\\\$)(?:\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)| # 1.1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[eE][+-]?[0-9]+\\\\b)|       # 1.E+3\\n  (?:\\\\B(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)|       # .1E+3\\n  (?:\\\\b[0-9]+[eE][+-]?[0-9]+\\\\b)|           # 1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+\\\\b)|                # 1.1\\n  (?:\\\\b[0-9]+(\\\\.)\\\\B)|                      # 1.\\n  (?:\\\\B(\\\\.)[0-9]+\\\\b)|                      # .1\\n  (?:\\\\b[0-9]+\\\\b(?!\\\\.))                     # 1\\n)(?!\\\\$)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"constant.numeric.decimal.ts\"\n                        },\n                        \"1\": {\n                            \"name\": \"meta.delimiter.decimal.period.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.delimiter.decimal.period.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.delimiter.decimal.period.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.delimiter.decimal.period.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"meta.delimiter.decimal.period.ts\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.delimiter.decimal.period.ts\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"boolean-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.boolean.true.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\btrue\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.boolean.false.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bfalse\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"null-literal\": {\n            \"name\": \"constant.language.null.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bnull\\\\b(?!\\\\$)\"\n        },\n        \"this-literal\": {\n            \"name\": \"variable.language.this.ts\",\n            \"match\": \"(?<!\\\\$)((?<=\\\\.\\\\.\\\\.)|(?<!\\\\.))\\\\bthis\\\\b(?!\\\\$)\"\n        },\n        \"super-literal\": {\n            \"name\": \"variable.language.super.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bsuper\\\\b(?!\\\\$)\"\n        },\n        \"undefined-literal\": {\n            \"name\": \"constant.language.undefined.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bundefined\\\\b(?!\\\\$)\"\n        },\n        \"numericConstant-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.nan.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bNaN\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.infinity.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bInfinity\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"support-objects\": {\n            \"patterns\": [\n                {\n                    \"name\": \"variable.language.arguments.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(arguments)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.builtin.ts\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Array|ArrayBuffer|Atomics|Boolean|DataView|Date|Float32Array|Float64Array|Function|Generator\\n  |GeneratorFunction|Int8Array|Int16Array|Int32Array|Intl|Map|Number|Object|Promise|Proxy\\n  |Reflect|RegExp|Set|SharedArrayBuffer|SIMD|String|Symbol|TypedArray\\n  |Uint8Array|Uint16Array|Uint32Array|Uint8ClampedArray|WeakMap|WeakSet)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.error.ts\",\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b((Eval|Internal|Range|Reference|Syntax|Type|URI)?Error)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.function.ts\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(clear(Interval|Timeout)|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|\\n  isFinite|isNaN|parseFloat|parseInt|require|set(Interval|Timeout)|super|unescape|uneval)(?=\\\\s*\\\\()\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Math)(?:\\\\s*(\\\\.)\\\\s*(?:\\n  (abs|acos|acosh|asin|asinh|atan|atan2|atanh|cbrt|ceil|clz32|cos|cosh|exp|\\n  expm1|floor|fround|hypot|imul|log|log10|log1p|log2|max|min|pow|random|\\n  round|sign|sin|sinh|sqrt|tan|tanh|trunc)\\n  |\\n  (E|LN10|LN2|LOG10E|LOG2E|PI|SQRT1_2|SQRT2)))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.math.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.math.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.constant.property.math.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(console)(?:\\\\s*(\\\\.)\\\\s*(\\n  assert|clear|count|debug|dir|error|group|groupCollapsed|groupEnd|info|log\\n  |profile|profileEnd|table|time|timeEnd|timeStamp|trace|warn))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.class.console.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.console.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(JSON)(?:\\\\s*(\\\\.)\\\\s*(parse|stringify))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.json.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.json.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (constructor|length|prototype|__proto__)\\n  |\\n  (EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.variable.property.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.constant.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (?<!\\\\.|\\\\$) \\\\b (?:\\n  (document|event|navigator|performance|screen|window)\\n  |\\n  (AnalyserNode|ArrayBufferView|Attr|AudioBuffer|AudioBufferSourceNode|AudioContext|AudioDestinationNode|AudioListener\\n  |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule\\n  |CSSCounterStyleRule|CSSGroupingRule|CSSMatrix|CSSMediaRule|CSSPageRule|CSSPrimitiveValue|CSSRule|CSSRuleList|CSSStyleDeclaration\\n  |CSSStyleRule|CSSStyleSheet|CSSSupportsRule|CSSValue|CSSValueList|CanvasGradient|CanvasImageSource|CanvasPattern\\n  |CanvasRenderingContext2D|ChannelMergerNode|ChannelSplitterNode|CharacterData|ChromeWorker|CloseEvent|Comment|CompositionEvent\\n  |Console|ConvolverNode|Coordinates|Credential|CredentialsContainer|Crypto|CryptoKey|CustomEvent|DOMError|DOMException\\n  |DOMHighResTimeStamp|DOMImplementation|DOMString|DOMStringList|DOMStringMap|DOMTimeStamp|DOMTokenList|DataTransfer\\n  |DataTransferItem|DataTransferItemList|DedicatedWorkerGlobalScope|DelayNode|DeviceProximityEvent|DirectoryEntry\\n  |DirectoryEntrySync|DirectoryReader|DirectoryReaderSync|Document|DocumentFragment|DocumentTouch|DocumentType|DragEvent\\n  |DynamicsCompressorNode|Element|Entry|EntrySync|ErrorEvent|Event|EventListener|EventSource|EventTarget|FederatedCredential\\n  |FetchEvent|File|FileEntry|FileEntrySync|FileException|FileList|FileReader|FileReaderSync|FileSystem|FileSystemSync\\n  |FontFace|FormData|GainNode|Gamepad|GamepadButton|GamepadEvent|Geolocation|GlobalEventHandlers|HTMLAnchorElement\\n  |HTMLAreaElement|HTMLAudioElement|HTMLBRElement|HTMLBaseElement|HTMLBodyElement|HTMLButtonElement|HTMLCanvasElement\\n  |HTMLCollection|HTMLContentElement|HTMLDListElement|HTMLDataElement|HTMLDataListElement|HTMLDialogElement|HTMLDivElement\\n  |HTMLDocument|HTMLElement|HTMLEmbedElement|HTMLFieldSetElement|HTMLFontElement|HTMLFormControlsCollection|HTMLFormElement\\n  |HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLIFrameElement|HTMLImageElement|HTMLInputElement\\n  |HTMLKeygenElement|HTMLLIElement|HTMLLabelElement|HTMLLegendElement|HTMLLinkElement|HTMLMapElement|HTMLMediaElement\\n  |HTMLMetaElement|HTMLMeterElement|HTMLModElement|HTMLOListElement|HTMLObjectElement|HTMLOptGroupElement|HTMLOptionElement\\n  |HTMLOptionsCollection|HTMLOutputElement|HTMLParagraphElement|HTMLParamElement|HTMLPreElement|HTMLProgressElement\\n  |HTMLQuoteElement|HTMLScriptElement|HTMLSelectElement|HTMLShadowElement|HTMLSourceElement|HTMLSpanElement|HTMLStyleElement\\n  |HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement\\n  |HTMLTableRowElement|HTMLTableSectionElement|HTMLTextAreaElement|HTMLTimeElement|HTMLTitleElement|HTMLTrackElement\\n  |HTMLUListElement|HTMLUnknownElement|HTMLVideoElement|HashChangeEvent|History|IDBCursor|IDBCursorWithValue|IDBDatabase\\n  |IDBEnvironment|IDBFactory|IDBIndex|IDBKeyRange|IDBMutableFile|IDBObjectStore|IDBOpenDBRequest|IDBRequest|IDBTransaction\\n  |IDBVersionChangeEvent|IIRFilterNode|IdentityManager|ImageBitmap|ImageBitmapFactories|ImageData|Index|InputDeviceCapabilities\\n  |InputEvent|InstallEvent|InstallTrigger|KeyboardEvent|LinkStyle|LocalFileSystem|LocalFileSystemSync|Location|MIDIAccess\\n  |MIDIConnectionEvent|MIDIInput|MIDIInputMap|MIDIOutputMap|MediaElementAudioSourceNode|MediaError|MediaKeyMessageEvent\\n  |MediaKeySession|MediaKeyStatusMap|MediaKeySystemAccess|MediaKeySystemConfiguration|MediaKeys|MediaRecorder|MediaStream\\n  |MediaStreamAudioDestinationNode|MediaStreamAudioSourceNode|MessageChannel|MessageEvent|MessagePort|MouseEvent\\n  |MutationObserver|MutationRecord|NamedNodeMap|Navigator|NavigatorConcurrentHardware|NavigatorGeolocation|NavigatorID\\n  |NavigatorLanguage|NavigatorOnLine|Node|NodeFilter|NodeIterator|NodeList|NonDocumentTypeChildNode|Notification\\n  |OfflineAudioCompletionEvent|OfflineAudioContext|OscillatorNode|PageTransitionEvent|PannerNode|ParentNode|PasswordCredential\\n  |Path2D|PaymentAddress|PaymentRequest|PaymentResponse|Performance|PerformanceEntry|PerformanceFrameTiming|PerformanceMark\\n  |PerformanceMeasure|PerformanceNavigation|PerformanceNavigationTiming|PerformanceObserver|PerformanceObserverEntryList\\n  |PerformanceResourceTiming|PerformanceTiming|PeriodicSyncEvent|PeriodicWave|Plugin|Point|PointerEvent|PopStateEvent\\n  |PortCollection|Position|PositionError|PositionOptions|PresentationConnectionClosedEvent|PresentationConnectionList\\n  |PresentationReceiver|ProcessingInstruction|ProgressEvent|PromiseRejectionEvent|PushEvent|PushRegistrationManager\\n  |RTCCertificate|RTCConfiguration|RTCPeerConnection|RTCSessionDescriptionCallback|RTCStatsReport|RadioNodeList|RandomSource\\n  |Range|ReadableByteStream|RenderingContext|SVGAElement|SVGAngle|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement\\n  |SVGAnimateTransformElement|SVGAnimatedAngle|SVGAnimatedBoolean|SVGAnimatedEnumeration|SVGAnimatedInteger|SVGAnimatedLength\\n  |SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedPoints|SVGAnimatedPreserveAspectRatio\\n  |SVGAnimatedRect|SVGAnimatedString|SVGAnimatedTransformList|SVGAnimationElement|SVGCircleElement|SVGClipPathElement\\n  |SVGCursorElement|SVGDefsElement|SVGDescElement|SVGElement|SVGEllipseElement|SVGEvent|SVGFilterElement|SVGFontElement\\n  |SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement\\n  |SVGForeignObjectElement|SVGGElement|SVGGlyphElement|SVGGradientElement|SVGHKernElement|SVGImageElement|SVGLength\\n  |SVGLengthList|SVGLineElement|SVGLinearGradientElement|SVGMPathElement|SVGMaskElement|SVGMatrix|SVGMissingGlyphElement\\n  |SVGNumber|SVGNumberList|SVGPathElement|SVGPatternElement|SVGPoint|SVGPolygonElement|SVGPolylineElement|SVGPreserveAspectRatio\\n  |SVGRadialGradientElement|SVGRect|SVGRectElement|SVGSVGElement|SVGScriptElement|SVGSetElement|SVGStopElement|SVGStringList\\n  |SVGStylable|SVGStyleElement|SVGSwitchElement|SVGSymbolElement|SVGTRefElement|SVGTSpanElement|SVGTests|SVGTextElement\\n  |SVGTextPositioningElement|SVGTitleElement|SVGTransform|SVGTransformList|SVGTransformable|SVGUseElement|SVGVKernElement\\n  |SVGViewElement|ServiceWorker|ServiceWorkerContainer|ServiceWorkerGlobalScope|ServiceWorkerRegistration|ServiceWorkerState\\n  |ShadowRoot|SharedWorker|SharedWorkerGlobalScope|SourceBufferList|StereoPannerNode|Storage|StorageEvent|StyleSheet\\n  |StyleSheetList|SubtleCrypto|SyncEvent|Text|TextMetrics|TimeEvent|TimeRanges|Touch|TouchEvent|TouchList|Transferable\\n  |TreeWalker|UIEvent|USVString|VRDisplayCapabilities|ValidityState|WaveShaperNode|WebGL|WebGLActiveInfo|WebGLBuffer\\n  |WebGLContextEvent|WebGLFramebuffer|WebGLProgram|WebGLRenderbuffer|WebGLRenderingContext|WebGLShader|WebGLShaderPrecisionFormat\\n  |WebGLTexture|WebGLTimerQueryEXT|WebGLTransformFeedback|WebGLUniformLocation|WebGLVertexArrayObject|WebGLVertexArrayObjectOES\\n  |WebSocket|WebSockets|WebVTT|WheelEvent|Window|WindowBase64|WindowEventHandlers|WindowTimers|Worker|WorkerGlobalScope\\n  |WorkerLocation|WorkerNavigator|XMLHttpRequest|XMLHttpRequestEventTarget|XMLSerializer|XPathExpression|XPathResult\\n  |XSLTProcessor))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.dom.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.class.dom.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\\n  |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\\n  |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\\n  |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\\n  |\\n  (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\\n  |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\\n  |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\\n  |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\\n  |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\\n  |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\\n  |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\\n  |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\\n  |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\\n  |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\\n  |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\\n  |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\\n  |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\\n  |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\\n  |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\\n  |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\\n  |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\\n  |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\\n  |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\\n  |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\\n  |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\\n  |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\\n  |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\\n  |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\\n  |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\\n  |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\\\b(?!\\\\$|\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.constant.dom.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.dom.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.class.node.ts\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Buffer|EventEmitter|Server|Pipe|Socket|REPLServer|ReadStream|WriteStream|Stream\\n  |Inflate|Deflate|InflateRaw|DeflateRaw|GZip|GUnzip|Unzip|Zip)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(process)(?:(\\\\.)(?:\\n  (arch|argv|config|connected|env|execArgv|execPath|exitCode|mainModule|pid|platform|release|stderr|stdin|stdout|title|version|versions)\\n  |\\n  (abort|chdir|cwd|disconnect|exit|[sg]ete?[gu]id|send|[sg]etgroups|initgroups|kill|memoryUsage|nextTick|umask|uptime|hrtime)\\n))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.object.process.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.process.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.process.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(?:(exports)|(module)(?:(\\\\.)(exports|id|filename|loaded|parent|children))?)\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.type.object.module.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.type.object.module.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.type.object.module.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.variable.object.node.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(global|GLOBAL|root|__dirname|__filename)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s*\\n(?:\\n (on(?:Rowsinserted|Rowsdelete|Rowenter|Rowexit|Resize|Resizestart|Resizeend|Reset|\\n   Readystatechange|Mouseout|Mouseover|Mousedown|Mouseup|Mousemove|\\n   Before(?:cut|deactivate|unload|update|paste|print|editfocus|activate)|\\n   Blur|Scrolltop|Submit|Select|Selectstart|Selectionchange|Hover|Help|\\n   Change|Contextmenu|Controlselect|Cut|Cellchange|Clock|Close|Deactivate|\\n   Datasetchanged|Datasetcomplete|Dataavailable|Drop|Drag|Dragstart|Dragover|\\n   Dragdrop|Dragenter|Dragend|Dragleave|Dblclick|Unload|Paste|Propertychange|Error|\\n   Errorupdate|Keydown|Keyup|Keypress|Focus|Load|Activate|Afterupdate|Afterprint|Abort)\\n ) |\\n (shift|showModelessDialog|showModalDialog|showHelp|scroll|scrollX|scrollByPages|\\n   scrollByLines|scrollY|scrollTo|stop|strike|sizeToContent|sidebar|signText|sort|\\n   sup|sub|substr|substring|splice|split|send|set(?:Milliseconds|Seconds|Minutes|Hours|\\n   Month|Year|FullYear|Date|UTC(?:Milliseconds|Seconds|Minutes|Hours|Month|FullYear|Date)|\\n   Time|Hotkeys|Cursor|ZOptions|Active|Resizable|RequestHeader)|search|slice|\\n   savePreferences|small|home|handleEvent|navigate|char|charCodeAt|charAt|concat|\\n   contextual|confirm|compile|clear|captureEvents|call|createStyleSheet|createPopup|\\n   createEventObject|to(?:GMTString|UTCString|String|Source|UpperCase|LowerCase|LocaleString)|\\n   test|taint|taintEnabled|indexOf|italics|disableExternalCapture|dump|detachEvent|unshift|\\n   untaint|unwatch|updateCommands|join|javaEnabled|pop|push|plugins.refresh|paddings|parse|\\n   print|prompt|preference|enableExternalCapture|exec|execScript|valueOf|UTC|find|file|\\n   fileModifiedDate|fileSize|fileCreatedDate|fileUpdatedDate|fixed|fontsize|fontcolor|\\n   forward|fromCharCode|watch|link|load|lastIndexOf|anchor|attachEvent|atob|apply|alert|\\n   abort|routeEvents|resize|resizeBy|resizeTo|recalc|returnValue|replace|reverse|reload|\\n   releaseCapture|releaseEvents|go|get(?:Milliseconds|Seconds|Minutes|Hours|Month|Day|Year|FullYear|\\n   Time|Date|TimezoneOffset|UTC(?:Milliseconds|Seconds|Minutes|Hours|Day|Month|FullYear|Date)|\\n   Attention|Selection|ResponseHeader|AllResponseHeaders)|moveBy|moveBelow|moveTo|\\n   moveToAbsolute|moveAbove|mergeAttributes|match|margins|btoa|big|bold|borderWidths|blink|back\\n ) |\\n (acceptNode|add|addEventListener|addTextTrack|adoptNode|after|animate|append|\\n   appendChild|appendData|before|blur|canPlayType|captureStream|\\n   caretPositionFromPoint|caretRangeFromPoint|checkValidity|clear|click|\\n   cloneContents|cloneNode|cloneRange|close|closest|collapse|\\n   compareBoundaryPoints|compareDocumentPosition|comparePoint|contains|\\n   convertPointFromNode|convertQuadFromNode|convertRectFromNode|createAttribute|\\n   createAttributeNS|createCaption|createCDATASection|createComment|\\n   createContextualFragment|createDocument|createDocumentFragment|\\n   createDocumentType|createElement|createElementNS|createEntityReference|\\n   createEvent|createExpression|createHTMLDocument|createNodeIterator|\\n   createNSResolver|createProcessingInstruction|createRange|createShadowRoot|\\n   createTBody|createTextNode|createTFoot|createTHead|createTreeWalker|delete|\\n   deleteCaption|deleteCell|deleteContents|deleteData|deleteRow|deleteTFoot|\\n   deleteTHead|detach|disconnect|dispatchEvent|elementFromPoint|elementsFromPoint|\\n   enableStyleSheetsForSet|entries|evaluate|execCommand|exitFullscreen|\\n   exitPointerLock|expand|extractContents|fastSeek|firstChild|focus|forEach|get|\\n   getAll|getAnimations|getAttribute|getAttributeNames|getAttributeNode|\\n   getAttributeNodeNS|getAttributeNS|getBoundingClientRect|getBoxQuads|\\n   getClientRects|getContext|getDestinationInsertionPoints|getElementById|\\n   getElementsByClassName|getElementsByName|getElementsByTagName|\\n   getElementsByTagNameNS|getItem|getNamedItem|getSelection|getStartDate|\\n   getVideoPlaybackQuality|has|hasAttribute|hasAttributeNS|hasAttributes|\\n   hasChildNodes|hasFeature|hasFocus|importNode|initEvent|insertAdjacentElement|\\n   insertAdjacentHTML|insertAdjacentText|insertBefore|insertCell|insertData|\\n   insertNode|insertRow|intersectsNode|isDefaultNamespace|isEqualNode|\\n   isPointInRange|isSameNode|item|key|keys|lastChild|load|lookupNamespaceURI|\\n   lookupPrefix|matches|move|moveAttribute|moveAttributeNode|moveChild|\\n   moveNamedItem|namedItem|nextNode|nextSibling|normalize|observe|open|\\n   parentNode|pause|play|postMessage|prepend|preventDefault|previousNode|\\n   previousSibling|probablySupportsContext|queryCommandEnabled|\\n   queryCommandIndeterm|queryCommandState|queryCommandSupported|queryCommandValue|\\n   querySelector|querySelectorAll|registerContentHandler|registerElement|\\n   registerProtocolHandler|releaseCapture|releaseEvents|remove|removeAttribute|\\n   removeAttributeNode|removeAttributeNS|removeChild|removeEventListener|\\n   removeItem|replace|replaceChild|replaceData|replaceWith|reportValidity|\\n   requestFullscreen|requestPointerLock|reset|scroll|scrollBy|scrollIntoView|\\n   scrollTo|seekToNextFrame|select|selectNode|selectNodeContents|set|setAttribute|\\n   setAttributeNode|setAttributeNodeNS|setAttributeNS|setCapture|\\n   setCustomValidity|setEnd|setEndAfter|setEndBefore|setItem|setNamedItem|\\n   setRangeText|setSelectionRange|setSinkId|setStart|setStartAfter|setStartBefore|\\n   slice|splitText|stepDown|stepUp|stopImmediatePropagation|stopPropagation|\\n   submit|substringData|supports|surroundContents|takeRecords|terminate|toBlob|\\n   toDataURL|toggle|toString|values|write|writeln\\n )\\n)(?=\\\\s*\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.function.event-handler.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.dom.ts\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"identifiers\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#object-identifiers\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:(\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.property.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.property.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"variable.other.constant.ts\",\n                    \"match\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.ts\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"object-identifiers\": {\n            \"patterns\": [\n                {\n                    \"name\": \"support.class.ts\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\\\.\\\\s*prototype\\\\b(?!\\\\$))\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(\\\\.)\\\\s*(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.object.property.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.object.property.ts\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.constant.object.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.object.ts\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"type-annotation\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.annotation.ts\",\n                    \"begin\": \"(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.ts\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=$|^|[,);\\\\}\\\\]]|//)|(?==[^>])|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.annotation.ts\",\n                    \"begin\": \"(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.ts\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=[,);\\\\}\\\\]]|//)|(?==[^>])|(?=^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$))|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.return.type.ts\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.ts\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])(?=$|^|[{};,]|//)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.return.type.ts\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.ts\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])((?=[{};,]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<=[:|&])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"arrow-return-type\": {\n            \"name\": \"meta.return.type.arrow.ts\",\n            \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.type.annotation.ts\"\n                }\n            },\n            \"end\":\n                \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=[:])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-parameters\": {\n            \"name\": \"meta.type.parameters.ts\",\n            \"begin\": \"(<)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.begin.ts\"\n                }\n            },\n            \"end\": \"(>)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.end.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"storage.modifier.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(extends)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.ts\",\n                    \"match\": \"\\\\=(?!>)\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#type-primitive\"\n                },\n                {\n                    \"include\": \"#type-builtin-literals\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type-tuple\"\n                },\n                {\n                    \"include\": \"#type-object\"\n                },\n                {\n                    \"include\": \"#type-operators\"\n                },\n                {\n                    \"include\": \"#type-fn-type-parameters\"\n                },\n                {\n                    \"include\": \"#type-paren-or-function-parameters\"\n                },\n                {\n                    \"include\": \"#type-function-return-type\"\n                },\n                {\n                    \"include\": \"#type-name\"\n                }\n            ]\n        },\n        \"type-primitive\": {\n            \"name\": \"support.type.primitive.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(string|number|boolean|symbol|any|void|never)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-builtin-literals\": {\n            \"name\": \"support.type.builtin.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(this|true|false|undefined|null|object)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-tuple\": {\n            \"name\": \"meta.type.tuple.ts\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.ts\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type-object\": {\n            \"name\": \"meta.object.type.ts\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-mapped-type-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.ts\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-paren-or-function-parameters\": {\n            \"name\": \"meta.type.paren.cover.ts\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.ts\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                }\n            ]\n        },\n        \"type-fn-type-parameters\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.constructor.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?=\\\\s*\\\\<)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.type.constructor.ts\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b\\\\s*(?=\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.ts\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.ts\",\n                    \"begin\":\n                        \"(?x)(\\n  (?=\\n    [(]\\\\s*(\\n      ([)]) |\\n      (\\\\.\\\\.\\\\.) |\\n      ([_$[:alnum:]]+\\\\s*(\\n        ([:,?=])|\\n        ([)]\\\\s*=>)\\n      ))\\n    )\\n  )\\n)\",\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.function.return.ts\",\n                    \"begin\": \"(=>)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.arrow.ts\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])(?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.return.ts\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.ts\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])((?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<==>)(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-operators\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"begin\": \"([&|])(?=\\\\s*\\\\{)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.ts\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"[&|]\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.ts\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\S)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.keyof.ts\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bkeyof\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"type-predicate-operator\": {\n            \"name\": \"keyword.operator.expression.is.ts\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bis\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-name\": {\n            \"patterns\": [\n                {\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.ts\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.ts\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"punctuation-comma\": {\n            \"name\": \"punctuation.separator.comma.ts\",\n            \"match\": \",\"\n        },\n        \"punctuation-semicolon\": {\n            \"name\": \"punctuation.terminator.statement.ts\",\n            \"match\": \";\"\n        },\n        \"punctuation-accessor\": {\n            \"name\": \"punctuation.accessor.ts\",\n            \"match\": \"\\\\.\"\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#qstring-single\"\n                },\n                {\n                    \"include\": \"#qstring-double\"\n                }\n            ]\n        },\n        \"qstring-double\": {\n            \"name\": \"string.quoted.double.ts\",\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ts\"\n                }\n            },\n            \"end\": \"(\\\")|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.ts\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"qstring-single\": {\n            \"name\": \"string.quoted.single.ts\",\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.ts\"\n                }\n            },\n            \"end\": \"(\\\\')|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.ts\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"string-character-escape\": {\n            \"name\": \"constant.character.escape.ts\",\n            \"match\": \"\\\\\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)\"\n        },\n        \"template\": {\n            \"name\": \"string.template.ts\",\n            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)?(`)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.tagged-template.ts\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.template.begin.ts\"\n                }\n            },\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.template.end.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#template-substitution-element\"\n                },\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"template-substitution-element\": {\n            \"name\": \"meta.template.expression.ts\",\n            \"begin\": \"\\\\$\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.begin.ts\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.end.ts\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ],\n            \"contentName\": \"meta.embedded.line.ts\"\n        },\n        \"regex\": {\n            \"patterns\": [\n                {\n                    \"name\": \"string.regexp.ts\",\n                    \"begin\":\n                        \"(?<=[=(:,\\\\[?+!]|return|case|=>|&&|\\\\|\\\\||\\\\*\\\\/)\\\\s*(\\\\/)(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.ts\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.regexp.ts\",\n                    \"begin\":\n                        \"(?<![_$[:alnum:])])\\\\/(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.ts\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"regexp\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.anchor.regexp\",\n                    \"match\": \"\\\\\\\\[bB]|\\\\^|\\\\$\"\n                },\n                {\n                    \"name\": \"keyword.other.back-reference.regexp\",\n                    \"match\": \"\\\\\\\\[1-9]\\\\d*\"\n                },\n                {\n                    \"name\": \"keyword.operator.quantifier.regexp\",\n                    \"match\": \"[?+*]|\\\\{(\\\\d+,\\\\d+|\\\\d+,|,\\\\d+|\\\\d+)\\\\}\\\\??\"\n                },\n                {\n                    \"name\": \"keyword.operator.or.regexp\",\n                    \"match\": \"\\\\|\"\n                },\n                {\n                    \"name\": \"meta.group.assertion.regexp\",\n                    \"begin\": \"(\\\\()((\\\\?=)|(\\\\?!))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.group.assertion.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.assertion.look-ahead.regexp\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.assertion.negative-look-ahead.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.group.regexp\",\n                    \"begin\": \"\\\\((\\\\?:)?\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.no-capture.regexp\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"constant.other.character-class.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"constant.other.character-class.range.regexp\",\n                            \"match\":\n                                \"(?:.|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\\\\-(?:[^\\\\]\\\\\\\\]|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"2\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"3\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                },\n                                \"4\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"5\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"6\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#regex-character-class\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#regex-character-class\"\n                }\n            ]\n        },\n        \"regex-character-class\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.character-class.regexp\",\n                    \"match\": \"\\\\\\\\[wWsSdDtrnvf]|\\\\.\"\n                },\n                {\n                    \"name\": \"constant.character.numeric.regexp\",\n                    \"match\": \"\\\\\\\\([0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})\"\n                },\n                {\n                    \"name\": \"constant.character.control.regexp\",\n                    \"match\": \"\\\\\\\\c[A-Z]\"\n                },\n                {\n                    \"name\": \"constant.character.escape.backslash.regexp\",\n                    \"match\": \"\\\\\\\\.\"\n                }\n            ]\n        },\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.block.documentation.ts\",\n                    \"begin\": \"/\\\\*\\\\*(?!/)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#docblock\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"comment.block.ts\",\n                    \"begin\": \"(/\\\\*)(?:\\\\s*((@)internal)(?=\\\\s|(\\\\*/)))?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.internaldeclaration.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.ts\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.ts\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"comment.line.double-slash.ts\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.comment.ts\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.internaldeclaration.ts\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.ts\"\n                        }\n                    },\n                    \"end\": \"(?=^)\",\n                    \"contentName\": \"comment.line.double-slash.ts\"\n                }\n            ]\n        },\n        \"directives\": {\n            \"name\": \"comment.line.triple-slash.directive.ts\",\n            \"begin\":\n                \"^(///)\\\\s*(?=<(reference|amd-dependency|amd-module)(\\\\s+(path|types|no-default-lib|name)\\\\s*=\\\\s*((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")))+\\\\s*/>\\\\s*$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.ts\"\n                }\n            },\n            \"end\": \"(?=^)\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.tag.ts\",\n                    \"begin\": \"(<)(reference|amd-dependency|amd-module)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.directive.ts\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.directive.ts\"\n                        }\n                    },\n                    \"end\": \"/>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.tag.directive.ts\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"entity.other.attribute-name.directive.ts\",\n                            \"match\": \"path|types|no-default-lib|name\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.assignment.ts\",\n                            \"match\": \"=\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"docblock\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n((@)(?:access|api))\\n\\\\s+\\n(private|protected|public)\\n\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.access-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)author)\\n\\\\s+\\n(\\n  [^@\\\\s<>*/]\\n  (?:[^@<>*/]|\\\\*[^/])*\\n)\\n(?:\\n  \\\\s*\\n  (<)\\n  ([^>\\\\s]+)\\n  (>)\\n)?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"constant.other.email.link.underline.jsdoc\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)borrows) \\\\s+\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <that namepath>\\n\\\\s+ (as) \\\\s+              # as\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <this namepath>\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.control.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.example.jsdoc\",\n                    \"begin\": \"((@)example)\\\\s+\",\n                    \"end\": \"(?=@|\\\\*/)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"^\\\\s\\\\*\\\\s+\"\n                        },\n                        {\n                            \"contentName\": \"constant.other.description.jsdoc\",\n                            \"begin\": \"\\\\G(<)caption(>)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            },\n                            \"end\": \"(</)caption(>)|(?=\\\\*/)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"[^\\\\s@*](?:[^*]|\\\\*[^/])*\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"source.embedded.ts\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x) ((@)kind) \\\\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.symbol-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)see)\\n\\\\s+\\n(?:\\n  # URL\\n  (\\n    (?=https?://)\\n    (?:[^\\\\s*]|\\\\*[^/])+\\n  )\\n  |\\n  # JSDoc namepath\\n  (\\n    (?!\\n      # Avoid matching bare URIs (also acceptable as links)\\n      https?://\\n      |\\n      # Avoid matching {@inline tags}; we match those below\\n      (?:\\\\[[^\\\\[\\\\]]*\\\\])? # Possible description [preceding]{@tag}\\n      {@(?:link|linkcode|linkplain|tutorial)\\\\b\\n    )\\n    # Matched namepath\\n    (?:[^@\\\\s*/]|\\\\*[^/])+\\n  )\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.link.underline.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)template)\\n\\\\s+\\n# One or more valid identifiers\\n(\\n  [A-Za-z_$]         # First character: non-numeric word character\\n  [\\\\w$.\\\\[\\\\]]*        # Rest of identifier\\n  (?:                # Possible list of additional identifiers\\n    \\\\s* , \\\\s*\\n    [A-Za-z_$]\\n    [\\\\w$.\\\\[\\\\]]*\\n  )*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:arg|argument|const|constant|member|namespace|param|var)\\n)\\n\\\\s+\\n(\\n  [A-Za-z_$]\\n  [\\\\w$.\\\\[\\\\]]*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"((@)typedef)\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"entity.name.type.instance.jsdoc\",\n                            \"match\": \"(?:[^@\\\\s*/]|\\\\*[^/])+\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\": \"([A-Za-z_$][\\\\w$.\\\\[\\\\]]*)\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\":\n                                \"(?x)\\n(\\\\[)\\\\s*\\n[\\\\w$]+\\n(?:\\n  (?:\\\\[\\\\])?                                        # Foo[ ].bar properties within an array\\n  \\\\.                                                # Foo.Bar namespaced parameter\\n  [\\\\w$]+\\n)*\\n(?:\\n  \\\\s*\\n  (=)                                                # [foo=bar] Default parameter value\\n  \\\\s*\\n  (\\n    # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\\n    (?>\\n      \\\"(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!\\\"))|[^*\\\\\\\\])*?\\\" |                      # [foo=\\\"bar\\\"] Double-quoted\\n      '(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!'))|[^*\\\\\\\\])*?' |                      # [foo='bar'] Single-quoted\\n      \\\\[ (?:(?:\\\\*(?!/))|[^*])*? \\\\] |                                # [foo=[1,2]] Array literal\\n      (?:(?:\\\\*(?!/))|\\\\s(?!\\\\s*\\\\])|\\\\[.*?(?:\\\\]|(?=\\\\*/))|[^*\\\\s\\\\[\\\\]])*   # Everything else\\n    )*\\n  )\\n)?\\n\\\\s*(?:(\\\\])((?:[^*\\\\s]|\\\\*[^\\\\s/])+)?|(?=\\\\*/))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.begin.bracket.square.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"keyword.operator.assignment.jsdoc\"\n                                },\n                                \"3\": {\n                                    \"name\": \"source.embedded.ts\"\n                                },\n                                \"4\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.end.bracket.square.jsdoc\"\n                                },\n                                \"5\": {\n                                    \"name\": \"invalid.illegal.syntax.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:define|enum|exception|export|extends|lends|implements|modifies\\n  |namespace|private|protected|returns?|suppress|this|throws|type\\n  |yields?)\\n)\\n\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:alias|augments|callback|constructs|emits|event|fires|exports?\\n  |extends|external|function|func|host|lends|listens|interface|memberof!?\\n  |method|module|mixes|mixin|name|requires|see|this|typedef|uses)\\n)\\n\\\\s+\\n(\\n  (?:\\n    [^{}@\\\\s*] | \\\\*[^/]\\n  )+\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"contentName\": \"variable.other.jsdoc\",\n                    \"begin\": \"((@)(?:default(?:value)?|license|version))\\\\s+(([''\\\"]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(\\\\3)|(?=$|\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"((@)(?:default(?:value)?|license|tutorial|variation|version))\\\\s+([^\\\\s*]+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"storage.type.class.jsdoc\",\n                    \"match\":\n                        \"(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#inline-tags\"\n                }\n            ]\n        },\n        \"brackets\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\[\",\n                    \"end\": \"\\\\]|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"inline-tags\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.description.jsdoc\",\n                    \"match\": \"(\\\\[)[^\\\\]]+(\\\\])(?={@(?:link|linkcode|linkplain|tutorial))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.square.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.square.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"({)((@)(?:link(?:code|plain)?|tutorial))\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.inline.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\G((?=https?://)(?:[^|}\\\\s*]|\\\\*[/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.link.underline.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"\\\\G((?:[^{}@\\\\s|*]|\\\\*[^/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.description.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsdoctype\": {\n            \"patterns\": [\n                {\n                    \"name\": \"invalid.illegal.type.jsdoc\",\n                    \"match\": \"\\\\G{(?:[^}*]|\\\\*[^/}])+$\"\n                },\n                {\n                    \"contentName\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"\\\\G({)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"((}))\\\\s*|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json",
    "content": "{\n    \"information_for_contributors\": [\n        \"This file has been converted from https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage\",\n        \"If you want to provide a fix or improvement, please create a pull request against the original repository.\",\n        \"Once accepted there, we are happy to receive an update request.\"\n    ],\n    \"version\":\n        \"https://github.com/Microsoft/TypeScript-TmLanguage/commit/8361b1a232501c67911c81a4664a9460d7922c6b\",\n    \"name\": \"TypeScriptReact\",\n    \"scopeName\": \"source.tsx\",\n    \"fileTypes\": [\"tsx\"],\n    \"uuid\": \"805375ec-d614-41f5-8993-5843fe63ea82\",\n    \"patterns\": [\n        {\n            \"include\": \"#directives\"\n        },\n        {\n            \"include\": \"#statements\"\n        },\n        {\n            \"name\": \"comment.line.shebang.ts\",\n            \"match\": \"\\\\A(#!).*(?=$)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.ts\"\n                }\n            }\n        }\n    ],\n    \"repository\": {\n        \"statements\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#declaration\"\n                },\n                {\n                    \"include\": \"#control-statement\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#function-declaration\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#interface-declaration\"\n                },\n                {\n                    \"include\": \"#enum-declaration\"\n                },\n                {\n                    \"include\": \"#namespace-declaration\"\n                },\n                {\n                    \"include\": \"#type-alias-declaration\"\n                },\n                {\n                    \"include\": \"#import-equals-declaration\"\n                },\n                {\n                    \"include\": \"#import-declaration\"\n                },\n                {\n                    \"include\": \"#export-declaration\"\n                }\n            ]\n        },\n        \"control-statement\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#switch-statement\"\n                },\n                {\n                    \"include\": \"#for-loop\"\n                },\n                {\n                    \"name\": \"keyword.control.trycatch.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(catch|finally|throw|try)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.loop.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(break|continue|do|goto|while)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.flow.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(return)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.switch.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(case|default|switch)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.conditional.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(else|if)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.control.with.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(with)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.other.debugger.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(debugger)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"storage.modifier.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(declare)\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"expression\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#regex\"\n                },\n                {\n                    \"include\": \"#template\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#function-expression\"\n                },\n                {\n                    \"include\": \"#class-expression\"\n                },\n                {\n                    \"include\": \"#arrow-function\"\n                },\n                {\n                    \"include\": \"#cast\"\n                },\n                {\n                    \"include\": \"#ternary-expression\"\n                },\n                {\n                    \"include\": \"#new-expr\"\n                },\n                {\n                    \"include\": \"#object-literal\"\n                },\n                {\n                    \"include\": \"#expression-operators\"\n                },\n                {\n                    \"include\": \"#function-call\"\n                },\n                {\n                    \"include\": \"#literal\"\n                },\n                {\n                    \"include\": \"#support-objects\"\n                },\n                {\n                    \"include\": \"#identifiers\"\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                }\n            ]\n        },\n        \"decorator\": {\n            \"name\": \"meta.decorator.tsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\@\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.decorator.tsx\"\n                }\n            },\n            \"end\": \"(?=\\\\s)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"var-expr\": {\n            \"name\": \"meta.var.expr.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(var|let|const(?!\\\\s+enum\\\\b))\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.tsx\"\n                }\n            },\n            \"end\": \"(?=$|^|;|}|(\\\\s+(of|in)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#destructuring-variable\"\n                },\n                {\n                    \"include\": \"#var-single-variable\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(,)\\\\s*(?!\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.separator.comma.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<!,)((?==|;|}|(\\\\s+(of|in)\\\\s+)|^\\\\s*$))|((?<=\\\\S)(?=\\\\s*$))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#destructuring-variable\"\n                        },\n                        {\n                            \"include\": \"#var-single-variable\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"var-single-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.var-single-variable.expr.tsx\",\n                    \"begin\":\n                        \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.tsx entity.name.function.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.tsx\",\n                    \"begin\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.tsx variable.other.constant.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.var-single-variable.expr.tsx\",\n                    \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"meta.definition.variable.tsx variable.other.readwrite.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#var-single-variable-type-annotation\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"var-single-variable-type-annotation\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                }\n            ]\n        },\n        \"destructuring-variable\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.object-binding-pattern-variable.tsx\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\{)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.array-binding-pattern-variable.tsx\",\n                    \"begin\": \"(?<!=|:|of|in)\\\\s*(?=\\\\[)\",\n                    \"end\": \"(?=$|^|[;,=}]|(\\\\s+(of|in)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-binding-pattern\"\n                        },\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"object-binding-element-propertyName\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.destructuring.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"variable.object.property.tsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-variable-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-variable-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"meta.definition.variable.tsx variable.other.readwrite.tsx\"\n                }\n            }\n        },\n        \"object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-binding-element\"\n                }\n            ]\n        },\n        \"array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.tsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-name\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"\\\\s*\\\\b(public|protected|private|readonly)(?=\\\\s+(public|protected|private|readonly)\\\\s+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:(this)|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)(?=\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.function.tsx variable.language.this.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.function.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?:\\\\s*\\\\b(public|private|protected|readonly)\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<!=|:)(?:((?<!\\\\.|\\\\$)\\\\bthis\\\\b(?!\\\\.|\\\\$))|([_$[:alpha:]][_$[:alnum:]]*))\\\\s*(\\\\??)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.rest.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.parameter.tsx variable.language.this.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"variable.parameter.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.operator.optional.tsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"destructuring-parameter\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.parameter.object-binding-pattern.tsx\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\{)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.object.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-object-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.paramter.array-binding-pattern.tsx\",\n                    \"begin\": \"(?<!=|:)\\\\s*(\\\\[)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\]\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.binding-pattern.array.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"parameter-object-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(:))\",\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#object-binding-element-propertyName\"\n                        },\n                        {\n                            \"include\": \"#parameter-binding-element\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"parameter-binding-element\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#parameter-object-binding-pattern\"\n                },\n                {\n                    \"include\": \"#parameter-array-binding-pattern\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter-rest\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                }\n            ]\n        },\n        \"destructuring-parameter-rest\": {\n            \"match\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"variable.parameter.tsx\"\n                }\n            }\n        },\n        \"parameter-object-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.object.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-object-binding-element\"\n                }\n            ]\n        },\n        \"parameter-array-binding-pattern\": {\n            \"begin\": \"(?:(\\\\.\\\\.\\\\.)\\\\s*)?(\\\\[)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.rest.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.tsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.binding-pattern.array.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#parameter-binding-element\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"field-declaration\": {\n            \"name\": \"meta.field.declaration.tsx\",\n            \"begin\":\n                \"(?<!\\\\()(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s+)?(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.tsx\"\n                }\n            },\n            \"end\":\n                \"(?=\\\\}|;|,|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))\",\n                    \"end\":\n                        \"(?=[};,=]|$|(^(?!(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\?\\\\s*)?(=|:))))|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-annotation\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        },\n                        {\n                            \"include\": \"#array-literal\"\n                        },\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.tsx entity.name.function.tsx\",\n                            \"match\":\n                                \"(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\\\?\\\\s*)?\\\\s*\\n# function assignment |\\n(=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)) |\\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\\n(:\\\\s*(\\n  (<) |\\n  ([(]\\\\s*(\\n    ([)]) |\\n    (\\\\.\\\\.\\\\.) |\\n    ([_$[:alnum:]]+\\\\s*(\\n      ([:,?=])|\\n      ([)]\\\\s*=>)\\n    ))\\n  ))\\n)))\"\n                        },\n                        {\n                            \"name\": \"meta.definition.property.tsx variable.object.property.tsx\",\n                            \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.optional.tsx\",\n                            \"match\": \"\\\\?\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"variable-initializer\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[,);}\\\\]])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(?<!=|!)(=)(?!=)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=[,);}\\\\]])|(?=^\\\\s*$)|(?<=\\\\S)(?<!=)(?=\\\\s*$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"function-declaration\": {\n            \"name\": \"meta.function.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.async.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.function.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.generator.asterisk.tsx\"\n                },\n                \"5\": {\n                    \"name\": \"meta.definition.function.tsx entity.name.function.tsx\"\n                }\n            },\n            \"end\": \"(?=$|^|;)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-expression\": {\n            \"name\": \"meta.function.expression.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(async)\\\\s+)?(function\\\\b)(?:\\\\s*(\\\\*))?(?:(?:\\\\s+|(?<=\\\\*))([_$[:alpha:]][_$[:alnum:]]*))?\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.function.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"meta.definition.function.tsx entity.name.function.tsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#function-body\"\n                }\n            ]\n        },\n        \"function-body\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                },\n                {\n                    \"include\": \"#return-type\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"method-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.method.declaration.tsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.property.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.generator.asterisk.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.method.declaration.tsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(public|private|protected)\\\\s+)?(?:\\\\b(abstract)\\\\s+)?(?:\\\\b(async)\\\\s+)?(?:(?:\\\\b(?:(new)|(constructor))\\\\b(?!\\\\$|\\\\.|:))|(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))?\\\\s*[\\\\(\\\\<]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.modifier.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.modifier.async.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.new.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"storage.type.tsx\"\n                        },\n                        \"6\": {\n                            \"name\": \"keyword.generator.asterisk.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        },\n                        {\n                            \"include\": \"#function-body\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"object-literal-method-declaration\": {\n            \"name\": \"meta.method.declaration.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.async.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.property.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"keyword.generator.asterisk.tsx\"\n                }\n            },\n            \"end\": \"(?=\\\\}|;|,)|(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#method-declaration-name\"\n                },\n                {\n                    \"include\": \"#function-body\"\n                },\n                {\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:\\\\b(async)\\\\s+)?(?:\\\\b(get|set)\\\\s+)?(?:(\\\\*)\\\\s*)?(?=((([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??))\\\\s*[\\\\(\\\\<])\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.property.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.generator.asterisk.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\(|\\\\<)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#method-declaration-name\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"method-declaration-name\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*)|(\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\]))\\\\s*(\\\\??)\\\\s*[\\\\(\\\\<])\",\n            \"end\": \"(?=\\\\(|\\\\<)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"name\": \"meta.definition.method.tsx entity.name.function.tsx\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                },\n                {\n                    \"name\": \"keyword.operator.optional.tsx\",\n                    \"match\": \"\\\\?\"\n                }\n            ]\n        },\n        \"arrow-function\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.arrow.tsx\",\n                    \"match\":\n                        \"(?:(?<!\\\\.|\\\\$)(\\\\basync)\\\\s+)?([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?==>)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.parameter.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.arrow.tsx\",\n                    \"begin\":\n                        \"(?x) (?:\\n  (?<!\\\\.|\\\\$)(\\\\basync)\\n)? ((?<![})!\\\\]])\\\\s*\\n  (?=\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  )\\n)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.modifier.async.tsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#type-parameters\"\n                        },\n                        {\n                            \"include\": \"#function-parameters\"\n                        },\n                        {\n                            \"include\": \"#arrow-return-type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.arrow.tsx\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\}|\\\\S)(?<!=>)|((?!\\\\{)(?=\\\\S))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#decl-block\"\n                        },\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"indexer-declaration\": {\n            \"name\": \"meta.indexer.declaration.tsx\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"variable.parameter.tsx\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type-annotation\"\n                }\n            ]\n        },\n        \"indexer-mapped-type-declaration\": {\n            \"name\": \"meta.indexer.mappedtype.declaration.tsx\",\n            \"begin\":\n                \"(?:(?<!\\\\.|\\\\$)\\\\b(readonly)\\\\s*)?(\\\\[)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\\\\s+(in)\\\\s+\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"keyword.operator.expression.in.tsx\"\n                }\n            },\n            \"end\": \"(\\\\])\\\\s*(\\\\?\\\\s*)?|$\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.operator.optional.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"function-parameters\": {\n            \"name\": \"meta.parameters.tsx\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.begin.tsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.parameters.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#destructuring-parameter\"\n                },\n                {\n                    \"include\": \"#parameter-name\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"name\": \"punctuation.separator.parameter.tsx\",\n                    \"match\": \",\"\n                }\n            ]\n        },\n        \"class-declaration\": {\n            \"name\": \"meta.class.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(class)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.class.tsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-expression\": {\n            \"name\": \"meta.class.tsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(class)\\\\b(?=\\\\s+|[<{]|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.type.class.tsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#class-declaration-or-expression-patterns\"\n                }\n            ]\n        },\n        \"class-declaration-or-expression-patterns\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.class.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"interface-declaration\": {\n            \"name\": \"meta.interface.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)\\\\b(?:(export)\\\\s+)?\\\\b(?:(abstract)\\\\s+)?\\\\b(interface)\\\\b(?=\\\\s+|/[/*])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.interface.tsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.interface.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#class-or-interface-body\"\n                }\n            ]\n        },\n        \"class-or-interface-heritage\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:\\\\b(extends|implements)\\\\b)(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"storage.modifier.tsx\"\n                }\n            },\n            \"end\": \"(?=\\\\{)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#class-or-interface-heritage\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)(?=\\\\s*[_$[:alpha:]][_$[:alnum:]]*(\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)*\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*([,<{]|extends|implements|//|/\\\\*))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.other.inherited-class.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"class-or-interface-body\": {\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#decorator\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"include\": \"#variable-initializer\"\n                },\n                {\n                    \"include\": \"#access-modifier\"\n                },\n                {\n                    \"include\": \"#property-accessor\"\n                },\n                {\n                    \"include\": \"#after-operator-block-as-object-literal\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"access-modifier\": {\n            \"name\": \"storage.modifier.tsx\",\n            \"match\":\n                \"(?<!\\\\.|\\\\$)\\\\b(abstract|public|protected|private|readonly|static)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"property-accessor\": {\n            \"name\": \"storage.type.property.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(get|set)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"enum-declaration\": {\n            \"name\": \"meta.enum.declaration.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?(?:\\\\b(const)\\\\s+)?\\\\b(enum)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.modifier.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"storage.type.enum.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"entity.name.type.enum.tsx\"\n                }\n            },\n            \"end\": \"(?<=\\\\})\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\}\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"variable.other.enummember.tsx\"\n                                }\n                            },\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"begin\":\n                                \"(?=((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")|(\\\\[([^\\\\[\\\\]]|\\\\[[^\\\\[\\\\]]*\\\\])+\\\\])))\",\n                            \"end\": \"(?=,|\\\\}|$)\",\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#string\"\n                                },\n                                {\n                                    \"include\": \"#array-literal\"\n                                },\n                                {\n                                    \"include\": \"#comment\"\n                                },\n                                {\n                                    \"include\": \"#variable-initializer\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"namespace-declaration\": {\n            \"name\": \"meta.namespace.declaration.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(namespace|module)\\\\s+(?=[_$[:alpha:]\\\"'`])\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.namespace.tsx\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\})|(?=;|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"name\": \"entity.name.type.module.tsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                },\n                {\n                    \"include\": \"#punctuation-accessor\"\n                },\n                {\n                    \"include\": \"#decl-block\"\n                }\n            ]\n        },\n        \"type-alias-declaration\": {\n            \"name\": \"meta.type.declaration.tsx\",\n            \"begin\":\n                \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(type)\\\\b\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"storage.type.type.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.type.alias.tsx\"\n                }\n            },\n            \"end\":\n                \"(?=[};]|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"match\": \"(=)\\\\s*\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.assignment.tsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"import-equals-declaration\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.import-equals.external.tsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(require)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"keyword.control.require.tsx\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.brace.round.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.import-equals.internal.tsx\",\n                    \"begin\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(=)\\\\s*(?!require\\\\b)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.import.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.alias.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.assignment.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=;|$|^)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"entity.name.type.module.tsx\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.accessor.tsx\"\n                                }\n                            }\n                        },\n                        {\n                            \"name\": \"variable.other.readwrite.tsx\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-declaration\": {\n            \"name\": \"meta.import.tsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?:(\\\\bexport)\\\\s+)?\\\\b(import)(?!(\\\\s*[:\\\\(])|(\\\\$|\\\\.))\\\\b\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.export.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.import.tsx\"\n                }\n            },\n            \"end\": \"(?=;|$|^)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-declaration\"\n                }\n            ]\n        },\n        \"export-declaration\": {\n            \"patterns\": [\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(export)\\\\s+(as)\\\\s+(namespace)\\\\s+([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.control.as.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"storage.type.namespace.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.module.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.export.default.tsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?:(?:\\\\s*(=))|(?:\\\\s+(default)(?=\\\\s+)))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.export.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.assignment.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"keyword.control.default.tsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.export.tsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(export)(?!(\\\\s*:)|(\\\\$))\\\\b\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.control.export.tsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?=;|$|\\\\babstract\\\\b|\\\\basync\\\\b|\\\\bclass\\\\b|\\\\bconst\\\\b|\\\\bdeclare\\\\b|\\\\benum\\\\b|\\\\bexport\\\\b|\\\\bfunction\\\\b|\\\\bimport\\\\b|\\\\binterface\\\\b|\\\\blet\\\\b|\\\\bmodule\\\\b|\\\\bnamespace\\\\b|\\\\btype\\\\b|\\\\bvar\\\\b)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#import-export-declaration\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"import-export-declaration\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#import-export-block\"\n                },\n                {\n                    \"name\": \"keyword.control.from.tsx\",\n                    \"match\": \"\\\\bfrom\\\\b\"\n                },\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-block\": {\n            \"name\": \"meta.block.tsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#import-export-clause\"\n                }\n            ]\n        },\n        \"import-export-clause\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)(?:(\\\\bdefault)|(\\\\*)|(\\\\b[_$[:alpha:]][_$[:alnum:]]*))\\\\s+(as)\\\\s+(\\\\b[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.default.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"constant.language.import-export-all.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.readwrite.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.control.as.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"variable.other.readwrite.alias.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"name\": \"constant.language.import-export-all.tsx\",\n                    \"match\": \"\\\\*\"\n                },\n                {\n                    \"name\": \"keyword.control.default.tsx\",\n                    \"match\": \"\\\\b(default)\\\\b\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.alias.tsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                }\n            ]\n        },\n        \"switch-statement\": {\n            \"name\": \"switch-statement.expr.tsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)(?=\\\\bswitch\\\\s*\\\\()\",\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"name\": \"switch-expression.expr.tsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(switch)\\\\s*(\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.switch.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.brace.round.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"meta.brace.round.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"switch-block.expr.tsx\",\n                    \"begin\": \"\\\\{\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.block.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"name\": \"case-clause.expr.tsx\",\n                            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(case|default(?=:))\\\\b(?!\\\\$|\\\\.)\",\n                            \"beginCaptures\": {\n                                \"1\": {\n                                    \"name\": \"keyword.control.switch.tsx\"\n                                }\n                            },\n                            \"end\": \":\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"punctuation.definition.section.case-statement.tsx\"\n                                }\n                            },\n                            \"patterns\": [\n                                {\n                                    \"include\": \"#expression\"\n                                }\n                            ]\n                        },\n                        {\n                            \"include\": \"#statements\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"for-loop\": {\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(for)(?:\\\\s+(await))?\\\\s*(\\\\()\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.control.loop.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"keyword.control.loop.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"meta.brace.round.tsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#var-expr\"\n                },\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                }\n            ]\n        },\n        \"decl-block\": {\n            \"name\": \"meta.block.tsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#statements\"\n                }\n            ]\n        },\n        \"after-operator-block-as-object-literal\": {\n            \"name\": \"meta.objectliteral.tsx\",\n            \"begin\":\n                \"(?<=[=(,\\\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\\\|\\\\||\\\\*)\\\\s*(\\\\{)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-literal\": {\n            \"name\": \"meta.objectliteral.tsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#object-member\"\n                }\n            ]\n        },\n        \"object-member\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#object-literal-method-declaration\"\n                },\n                {\n                    \"name\": \"meta.object.member.tsx meta.object-literal.key.tsx\",\n                    \"begin\": \"(?=\\\\[)\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#array-literal\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.tsx meta.object-literal.key.tsx\",\n                    \"begin\": \"(?=[\\\\'\\\\\\\"])\",\n                    \"end\": \"(?=:)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"match\": \"(?![_$[:alpha:]])([[:digit:]]+)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.tsx\"\n                        },\n                        \"1\": {\n                            \"name\": \"constant.numeric.decimal.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"match\":\n                        \"(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n)))\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.tsx\"\n                        },\n                        \"1\": {\n                            \"name\": \"entity.name.function.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"match\": \"(?:[_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=:)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"meta.object-literal.key.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(?=,|\\\\}|$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.readwrite.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"begin\": \"(?=[_$[:alpha:]][_$[:alnum:]]*\\\\s*=)\",\n                    \"end\": \"(?=,|\\\\}|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.object.member.tsx\",\n                    \"begin\": \":\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\":\n                                \"meta.object-literal.key.tsx punctuation.separator.key-value.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=,|\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#expression\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"ternary-expression\": {\n            \"begin\": \"(\\\\?)\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.tsx\"\n                }\n            },\n            \"end\": \"(:)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"keyword.operator.ternary.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"function-call\": {\n            \"begin\":\n                \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"end\":\n                \"(?<=\\\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.function-call.tsx\",\n                    \"begin\":\n                        \"(?=(([_$[:alpha:]][_$[:alnum:]]*\\\\s*\\\\.\\\\s*)*|(\\\\.\\\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))\",\n                    \"end\":\n                        \"(?=\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`]([^<>]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[\\\\\\\"\\\\'\\\\`][^<>]+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#literal\"\n                        },\n                        {\n                            \"include\": \"#support-objects\"\n                        },\n                        {\n                            \"include\": \"#object-identifiers\"\n                        },\n                        {\n                            \"include\": \"#punctuation-accessor\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.expression.import.tsx\",\n                            \"match\": \"(?![\\\\.\\\\$])\\\\bimport(?=\\\\s*[\\\\(]\\\\s*[\\\\\\\"\\\\'\\\\`])\"\n                        },\n                        {\n                            \"name\": \"entity.name.function.tsx\",\n                            \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"meta.type.parameters.tsx\",\n                    \"begin\": \"\\\\<\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.begin.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.typeparameters.end.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        },\n                        {\n                            \"include\": \"#punctuation-comma\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#paren-expression\"\n                }\n            ]\n        },\n        \"new-expr\": {\n            \"name\": \"new.expr.tsx\",\n            \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?!\\\\$|\\\\.)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.new.tsx\"\n                }\n            },\n            \"end\":\n                \"(?<=\\\\))|(?=[;),}\\\\]]|$|((?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.))|((?<!\\\\.|\\\\$)\\\\bfunction((\\\\s+[_$[:alpha:]][_$[:alnum:]]*)|(\\\\s*[\\\\(]))))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#paren-expression\"\n                },\n                {\n                    \"include\": \"#class-declaration\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"paren-expression\": {\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.tsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"cast\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx\"\n                }\n            ]\n        },\n        \"expression-operators\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.flow.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(await)\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(yield)\\\\b(?!\\\\$|\\\\.)(?:\\\\s*(\\\\*))?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.flow.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.generator.asterisk.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"keyword.operator.expression.delete.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bdelete\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.in.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bin\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.of.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.instanceof.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\binstanceof\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"name\": \"keyword.operator.new.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bnew\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.void.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bvoid\\\\b(?!\\\\$|\\\\.)\"\n                },\n                {\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(as)\\\\s+\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.as.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=$|^|[;,:})\\\\]]|((?<!\\\\.|\\\\$)\\\\b(as)\\\\s+))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"keyword.operator.spread.tsx\",\n                    \"match\": \"\\\\.\\\\.\\\\.\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.tsx\",\n                    \"match\": \"\\\\*=|(?<!\\\\()/=|%=|\\\\+=|\\\\-=\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.compound.bitwise.tsx\",\n                    \"match\": \"\\\\&=|\\\\^=|<<=|>>=|>>>=|\\\\|=\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.shift.tsx\",\n                    \"match\": \"<<|>>>|>>\"\n                },\n                {\n                    \"name\": \"keyword.operator.comparison.tsx\",\n                    \"match\": \"===|!==|==|!=\"\n                },\n                {\n                    \"name\": \"keyword.operator.relational.tsx\",\n                    \"match\": \"<=|>=|<>|<|>\"\n                },\n                {\n                    \"name\": \"keyword.operator.logical.tsx\",\n                    \"match\": \"\\\\!|&&|\\\\|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.bitwise.tsx\",\n                    \"match\": \"\\\\&|~|\\\\^|\\\\|\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.tsx\",\n                    \"match\": \"\\\\=\"\n                },\n                {\n                    \"name\": \"keyword.operator.decrement.tsx\",\n                    \"match\": \"--\"\n                },\n                {\n                    \"name\": \"keyword.operator.increment.tsx\",\n                    \"match\": \"\\\\+\\\\+\"\n                },\n                {\n                    \"name\": \"keyword.operator.arithmetic.tsx\",\n                    \"match\": \"%|\\\\*|/|-|\\\\+\"\n                },\n                {\n                    \"match\": \"(?<=[_$[:alnum:])])\\\\s*(/)(?![/*])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.arithmetic.tsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"typeof-operator\": {\n            \"name\": \"keyword.operator.expression.typeof.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\btypeof\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"literal\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#boolean-literal\"\n                },\n                {\n                    \"include\": \"#null-literal\"\n                },\n                {\n                    \"include\": \"#undefined-literal\"\n                },\n                {\n                    \"include\": \"#numericConstant-literal\"\n                },\n                {\n                    \"include\": \"#array-literal\"\n                },\n                {\n                    \"include\": \"#this-literal\"\n                },\n                {\n                    \"include\": \"#super-literal\"\n                }\n            ]\n        },\n        \"array-literal\": {\n            \"name\": \"meta.array.literal.tsx\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"numeric-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.numeric.hex.tsx\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(x|X)[0-9a-fA-F]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.binary.tsx\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(b|B)[01]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.numeric.octal.tsx\",\n                    \"match\": \"\\\\b(?<!\\\\$)0(o|O)?[0-7]+\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(?<!\\\\$)(?:\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)| # 1.1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[eE][+-]?[0-9]+\\\\b)|       # 1.E+3\\n  (?:\\\\B(\\\\.)[0-9]+[eE][+-]?[0-9]+\\\\b)|       # .1E+3\\n  (?:\\\\b[0-9]+[eE][+-]?[0-9]+\\\\b)|           # 1E+3\\n  (?:\\\\b[0-9]+(\\\\.)[0-9]+\\\\b)|                # 1.1\\n  (?:\\\\b[0-9]+(\\\\.)\\\\B)|                      # 1.\\n  (?:\\\\B(\\\\.)[0-9]+\\\\b)|                      # .1\\n  (?:\\\\b[0-9]+\\\\b(?!\\\\.))                     # 1\\n)(?!\\\\$)\",\n                    \"captures\": {\n                        \"0\": {\n                            \"name\": \"constant.numeric.decimal.tsx\"\n                        },\n                        \"1\": {\n                            \"name\": \"meta.delimiter.decimal.period.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"meta.delimiter.decimal.period.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.delimiter.decimal.period.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.delimiter.decimal.period.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"meta.delimiter.decimal.period.tsx\"\n                        },\n                        \"6\": {\n                            \"name\": \"meta.delimiter.decimal.period.tsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"boolean-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.boolean.true.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\btrue\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.boolean.false.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bfalse\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"null-literal\": {\n            \"name\": \"constant.language.null.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bnull\\\\b(?!\\\\$)\"\n        },\n        \"this-literal\": {\n            \"name\": \"variable.language.this.tsx\",\n            \"match\": \"(?<!\\\\$)((?<=\\\\.\\\\.\\\\.)|(?<!\\\\.))\\\\bthis\\\\b(?!\\\\$)\"\n        },\n        \"super-literal\": {\n            \"name\": \"variable.language.super.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bsuper\\\\b(?!\\\\$)\"\n        },\n        \"undefined-literal\": {\n            \"name\": \"constant.language.undefined.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bundefined\\\\b(?!\\\\$)\"\n        },\n        \"numericConstant-literal\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.language.nan.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bNaN\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"constant.language.infinity.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bInfinity\\\\b(?!\\\\$)\"\n                }\n            ]\n        },\n        \"support-objects\": {\n            \"patterns\": [\n                {\n                    \"name\": \"variable.language.arguments.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(arguments)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.builtin.tsx\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Array|ArrayBuffer|Atomics|Boolean|DataView|Date|Float32Array|Float64Array|Function|Generator\\n  |GeneratorFunction|Int8Array|Int16Array|Int32Array|Intl|Map|Number|Object|Promise|Proxy\\n  |Reflect|RegExp|Set|SharedArrayBuffer|SIMD|String|Symbol|TypedArray\\n  |Uint8Array|Uint16Array|Uint32Array|Uint8ClampedArray|WeakMap|WeakSet)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.class.error.tsx\",\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b((Eval|Internal|Range|Reference|Syntax|Type|URI)?Error)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"support.function.tsx\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(clear(Interval|Timeout)|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|\\n  isFinite|isNaN|parseFloat|parseInt|require|set(Interval|Timeout)|super|unescape|uneval)(?=\\\\s*\\\\()\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Math)(?:\\\\s*(\\\\.)\\\\s*(?:\\n  (abs|acos|acosh|asin|asinh|atan|atan2|atanh|cbrt|ceil|clz32|cos|cosh|exp|\\n  expm1|floor|fround|hypot|imul|log|log10|log1p|log2|max|min|pow|random|\\n  round|sign|sin|sinh|sqrt|tan|tanh|trunc)\\n  |\\n  (E|LN10|LN2|LOG10E|LOG2E|PI|SQRT1_2|SQRT2)))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.math.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.math.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.constant.property.math.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(console)(?:\\\\s*(\\\\.)\\\\s*(\\n  assert|clear|count|debug|dir|error|group|groupCollapsed|groupEnd|info|log\\n  |profile|profileEnd|table|time|timeEnd|timeStamp|trace|warn))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.class.console.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.console.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(JSON)(?:\\\\s*(\\\\.)\\\\s*(parse|stringify))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.constant.json.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.json.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (constructor|length|prototype|__proto__)\\n  |\\n  (EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.variable.property.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.constant.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (?<!\\\\.|\\\\$) \\\\b (?:\\n  (document|event|navigator|performance|screen|window)\\n  |\\n  (AnalyserNode|ArrayBufferView|Attr|AudioBuffer|AudioBufferSourceNode|AudioContext|AudioDestinationNode|AudioListener\\n  |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule\\n  |CSSCounterStyleRule|CSSGroupingRule|CSSMatrix|CSSMediaRule|CSSPageRule|CSSPrimitiveValue|CSSRule|CSSRuleList|CSSStyleDeclaration\\n  |CSSStyleRule|CSSStyleSheet|CSSSupportsRule|CSSValue|CSSValueList|CanvasGradient|CanvasImageSource|CanvasPattern\\n  |CanvasRenderingContext2D|ChannelMergerNode|ChannelSplitterNode|CharacterData|ChromeWorker|CloseEvent|Comment|CompositionEvent\\n  |Console|ConvolverNode|Coordinates|Credential|CredentialsContainer|Crypto|CryptoKey|CustomEvent|DOMError|DOMException\\n  |DOMHighResTimeStamp|DOMImplementation|DOMString|DOMStringList|DOMStringMap|DOMTimeStamp|DOMTokenList|DataTransfer\\n  |DataTransferItem|DataTransferItemList|DedicatedWorkerGlobalScope|DelayNode|DeviceProximityEvent|DirectoryEntry\\n  |DirectoryEntrySync|DirectoryReader|DirectoryReaderSync|Document|DocumentFragment|DocumentTouch|DocumentType|DragEvent\\n  |DynamicsCompressorNode|Element|Entry|EntrySync|ErrorEvent|Event|EventListener|EventSource|EventTarget|FederatedCredential\\n  |FetchEvent|File|FileEntry|FileEntrySync|FileException|FileList|FileReader|FileReaderSync|FileSystem|FileSystemSync\\n  |FontFace|FormData|GainNode|Gamepad|GamepadButton|GamepadEvent|Geolocation|GlobalEventHandlers|HTMLAnchorElement\\n  |HTMLAreaElement|HTMLAudioElement|HTMLBRElement|HTMLBaseElement|HTMLBodyElement|HTMLButtonElement|HTMLCanvasElement\\n  |HTMLCollection|HTMLContentElement|HTMLDListElement|HTMLDataElement|HTMLDataListElement|HTMLDialogElement|HTMLDivElement\\n  |HTMLDocument|HTMLElement|HTMLEmbedElement|HTMLFieldSetElement|HTMLFontElement|HTMLFormControlsCollection|HTMLFormElement\\n  |HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLIFrameElement|HTMLImageElement|HTMLInputElement\\n  |HTMLKeygenElement|HTMLLIElement|HTMLLabelElement|HTMLLegendElement|HTMLLinkElement|HTMLMapElement|HTMLMediaElement\\n  |HTMLMetaElement|HTMLMeterElement|HTMLModElement|HTMLOListElement|HTMLObjectElement|HTMLOptGroupElement|HTMLOptionElement\\n  |HTMLOptionsCollection|HTMLOutputElement|HTMLParagraphElement|HTMLParamElement|HTMLPreElement|HTMLProgressElement\\n  |HTMLQuoteElement|HTMLScriptElement|HTMLSelectElement|HTMLShadowElement|HTMLSourceElement|HTMLSpanElement|HTMLStyleElement\\n  |HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement\\n  |HTMLTableRowElement|HTMLTableSectionElement|HTMLTextAreaElement|HTMLTimeElement|HTMLTitleElement|HTMLTrackElement\\n  |HTMLUListElement|HTMLUnknownElement|HTMLVideoElement|HashChangeEvent|History|IDBCursor|IDBCursorWithValue|IDBDatabase\\n  |IDBEnvironment|IDBFactory|IDBIndex|IDBKeyRange|IDBMutableFile|IDBObjectStore|IDBOpenDBRequest|IDBRequest|IDBTransaction\\n  |IDBVersionChangeEvent|IIRFilterNode|IdentityManager|ImageBitmap|ImageBitmapFactories|ImageData|Index|InputDeviceCapabilities\\n  |InputEvent|InstallEvent|InstallTrigger|KeyboardEvent|LinkStyle|LocalFileSystem|LocalFileSystemSync|Location|MIDIAccess\\n  |MIDIConnectionEvent|MIDIInput|MIDIInputMap|MIDIOutputMap|MediaElementAudioSourceNode|MediaError|MediaKeyMessageEvent\\n  |MediaKeySession|MediaKeyStatusMap|MediaKeySystemAccess|MediaKeySystemConfiguration|MediaKeys|MediaRecorder|MediaStream\\n  |MediaStreamAudioDestinationNode|MediaStreamAudioSourceNode|MessageChannel|MessageEvent|MessagePort|MouseEvent\\n  |MutationObserver|MutationRecord|NamedNodeMap|Navigator|NavigatorConcurrentHardware|NavigatorGeolocation|NavigatorID\\n  |NavigatorLanguage|NavigatorOnLine|Node|NodeFilter|NodeIterator|NodeList|NonDocumentTypeChildNode|Notification\\n  |OfflineAudioCompletionEvent|OfflineAudioContext|OscillatorNode|PageTransitionEvent|PannerNode|ParentNode|PasswordCredential\\n  |Path2D|PaymentAddress|PaymentRequest|PaymentResponse|Performance|PerformanceEntry|PerformanceFrameTiming|PerformanceMark\\n  |PerformanceMeasure|PerformanceNavigation|PerformanceNavigationTiming|PerformanceObserver|PerformanceObserverEntryList\\n  |PerformanceResourceTiming|PerformanceTiming|PeriodicSyncEvent|PeriodicWave|Plugin|Point|PointerEvent|PopStateEvent\\n  |PortCollection|Position|PositionError|PositionOptions|PresentationConnectionClosedEvent|PresentationConnectionList\\n  |PresentationReceiver|ProcessingInstruction|ProgressEvent|PromiseRejectionEvent|PushEvent|PushRegistrationManager\\n  |RTCCertificate|RTCConfiguration|RTCPeerConnection|RTCSessionDescriptionCallback|RTCStatsReport|RadioNodeList|RandomSource\\n  |Range|ReadableByteStream|RenderingContext|SVGAElement|SVGAngle|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement\\n  |SVGAnimateTransformElement|SVGAnimatedAngle|SVGAnimatedBoolean|SVGAnimatedEnumeration|SVGAnimatedInteger|SVGAnimatedLength\\n  |SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedPoints|SVGAnimatedPreserveAspectRatio\\n  |SVGAnimatedRect|SVGAnimatedString|SVGAnimatedTransformList|SVGAnimationElement|SVGCircleElement|SVGClipPathElement\\n  |SVGCursorElement|SVGDefsElement|SVGDescElement|SVGElement|SVGEllipseElement|SVGEvent|SVGFilterElement|SVGFontElement\\n  |SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement\\n  |SVGForeignObjectElement|SVGGElement|SVGGlyphElement|SVGGradientElement|SVGHKernElement|SVGImageElement|SVGLength\\n  |SVGLengthList|SVGLineElement|SVGLinearGradientElement|SVGMPathElement|SVGMaskElement|SVGMatrix|SVGMissingGlyphElement\\n  |SVGNumber|SVGNumberList|SVGPathElement|SVGPatternElement|SVGPoint|SVGPolygonElement|SVGPolylineElement|SVGPreserveAspectRatio\\n  |SVGRadialGradientElement|SVGRect|SVGRectElement|SVGSVGElement|SVGScriptElement|SVGSetElement|SVGStopElement|SVGStringList\\n  |SVGStylable|SVGStyleElement|SVGSwitchElement|SVGSymbolElement|SVGTRefElement|SVGTSpanElement|SVGTests|SVGTextElement\\n  |SVGTextPositioningElement|SVGTitleElement|SVGTransform|SVGTransformList|SVGTransformable|SVGUseElement|SVGVKernElement\\n  |SVGViewElement|ServiceWorker|ServiceWorkerContainer|ServiceWorkerGlobalScope|ServiceWorkerRegistration|ServiceWorkerState\\n  |ShadowRoot|SharedWorker|SharedWorkerGlobalScope|SourceBufferList|StereoPannerNode|Storage|StorageEvent|StyleSheet\\n  |StyleSheetList|SubtleCrypto|SyncEvent|Text|TextMetrics|TimeEvent|TimeRanges|Touch|TouchEvent|TouchList|Transferable\\n  |TreeWalker|UIEvent|USVString|VRDisplayCapabilities|ValidityState|WaveShaperNode|WebGL|WebGLActiveInfo|WebGLBuffer\\n  |WebGLContextEvent|WebGLFramebuffer|WebGLProgram|WebGLRenderbuffer|WebGLRenderingContext|WebGLShader|WebGLShaderPrecisionFormat\\n  |WebGLTexture|WebGLTimerQueryEXT|WebGLTransformFeedback|WebGLUniformLocation|WebGLVertexArrayObject|WebGLVertexArrayObjectOES\\n  |WebSocket|WebSockets|WebVTT|WheelEvent|Window|WindowBase64|WindowEventHandlers|WindowTimers|Worker|WorkerGlobalScope\\n  |WorkerLocation|WorkerNavigator|XMLHttpRequest|XMLHttpRequestEventTarget|XMLSerializer|XPathExpression|XPathResult\\n  |XSLTProcessor))\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.dom.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.class.dom.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s* (?:\\n  (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\\n  |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\\n  |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\\n  |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\\n  |\\n  (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\\n  |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\\n  |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\\n  |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\\n  |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\\n  |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\\n  |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\\n  |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\\n  |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\\n  |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\\n  |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\\n  |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\\n  |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\\n  |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\\n  |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\\n  |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\\n  |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\\n  |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\\n  |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\\n  |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\\n  |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\\n  |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\\n  |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\\n  |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\\n  |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\\n  |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\\\b(?!\\\\$|\\\\s*(<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.constant.dom.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.dom.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.class.node.tsx\",\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(Buffer|EventEmitter|Server|Pipe|Socket|REPLServer|ReadStream|WriteStream|Stream\\n  |Inflate|Deflate|InflateRaw|DeflateRaw|GZip|GUnzip|Unzip|Zip)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?<!\\\\.|\\\\$)\\\\b(process)(?:(\\\\.)(?:\\n  (arch|argv|config|connected|env|execArgv|execPath|exitCode|mainModule|pid|platform|release|stderr|stdin|stdout|title|version|versions)\\n  |\\n  (abort|chdir|cwd|disconnect|exit|[sg]ete?[gu]id|send|[sg]etgroups|initgroups|kill|memoryUsage|nextTick|umask|uptime|hrtime)\\n))?\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.variable.object.process.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.variable.property.process.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.process.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?<!\\\\.|\\\\$)\\\\b(?:(exports)|(module)(?:(\\\\.)(exports|id|filename|loaded|parent|children))?)\\\\b(?!\\\\$)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"support.type.object.module.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.type.object.module.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.type.object.module.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"support.variable.object.node.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(global|GLOBAL|root|__dirname|__filename)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"match\":\n                        \"(?x) (\\\\.) \\\\s*\\n(?:\\n (on(?:Rowsinserted|Rowsdelete|Rowenter|Rowexit|Resize|Resizestart|Resizeend|Reset|\\n   Readystatechange|Mouseout|Mouseover|Mousedown|Mouseup|Mousemove|\\n   Before(?:cut|deactivate|unload|update|paste|print|editfocus|activate)|\\n   Blur|Scrolltop|Submit|Select|Selectstart|Selectionchange|Hover|Help|\\n   Change|Contextmenu|Controlselect|Cut|Cellchange|Clock|Close|Deactivate|\\n   Datasetchanged|Datasetcomplete|Dataavailable|Drop|Drag|Dragstart|Dragover|\\n   Dragdrop|Dragenter|Dragend|Dragleave|Dblclick|Unload|Paste|Propertychange|Error|\\n   Errorupdate|Keydown|Keyup|Keypress|Focus|Load|Activate|Afterupdate|Afterprint|Abort)\\n ) |\\n (shift|showModelessDialog|showModalDialog|showHelp|scroll|scrollX|scrollByPages|\\n   scrollByLines|scrollY|scrollTo|stop|strike|sizeToContent|sidebar|signText|sort|\\n   sup|sub|substr|substring|splice|split|send|set(?:Milliseconds|Seconds|Minutes|Hours|\\n   Month|Year|FullYear|Date|UTC(?:Milliseconds|Seconds|Minutes|Hours|Month|FullYear|Date)|\\n   Time|Hotkeys|Cursor|ZOptions|Active|Resizable|RequestHeader)|search|slice|\\n   savePreferences|small|home|handleEvent|navigate|char|charCodeAt|charAt|concat|\\n   contextual|confirm|compile|clear|captureEvents|call|createStyleSheet|createPopup|\\n   createEventObject|to(?:GMTString|UTCString|String|Source|UpperCase|LowerCase|LocaleString)|\\n   test|taint|taintEnabled|indexOf|italics|disableExternalCapture|dump|detachEvent|unshift|\\n   untaint|unwatch|updateCommands|join|javaEnabled|pop|push|plugins.refresh|paddings|parse|\\n   print|prompt|preference|enableExternalCapture|exec|execScript|valueOf|UTC|find|file|\\n   fileModifiedDate|fileSize|fileCreatedDate|fileUpdatedDate|fixed|fontsize|fontcolor|\\n   forward|fromCharCode|watch|link|load|lastIndexOf|anchor|attachEvent|atob|apply|alert|\\n   abort|routeEvents|resize|resizeBy|resizeTo|recalc|returnValue|replace|reverse|reload|\\n   releaseCapture|releaseEvents|go|get(?:Milliseconds|Seconds|Minutes|Hours|Month|Day|Year|FullYear|\\n   Time|Date|TimezoneOffset|UTC(?:Milliseconds|Seconds|Minutes|Hours|Day|Month|FullYear|Date)|\\n   Attention|Selection|ResponseHeader|AllResponseHeaders)|moveBy|moveBelow|moveTo|\\n   moveToAbsolute|moveAbove|mergeAttributes|match|margins|btoa|big|bold|borderWidths|blink|back\\n ) |\\n (acceptNode|add|addEventListener|addTextTrack|adoptNode|after|animate|append|\\n   appendChild|appendData|before|blur|canPlayType|captureStream|\\n   caretPositionFromPoint|caretRangeFromPoint|checkValidity|clear|click|\\n   cloneContents|cloneNode|cloneRange|close|closest|collapse|\\n   compareBoundaryPoints|compareDocumentPosition|comparePoint|contains|\\n   convertPointFromNode|convertQuadFromNode|convertRectFromNode|createAttribute|\\n   createAttributeNS|createCaption|createCDATASection|createComment|\\n   createContextualFragment|createDocument|createDocumentFragment|\\n   createDocumentType|createElement|createElementNS|createEntityReference|\\n   createEvent|createExpression|createHTMLDocument|createNodeIterator|\\n   createNSResolver|createProcessingInstruction|createRange|createShadowRoot|\\n   createTBody|createTextNode|createTFoot|createTHead|createTreeWalker|delete|\\n   deleteCaption|deleteCell|deleteContents|deleteData|deleteRow|deleteTFoot|\\n   deleteTHead|detach|disconnect|dispatchEvent|elementFromPoint|elementsFromPoint|\\n   enableStyleSheetsForSet|entries|evaluate|execCommand|exitFullscreen|\\n   exitPointerLock|expand|extractContents|fastSeek|firstChild|focus|forEach|get|\\n   getAll|getAnimations|getAttribute|getAttributeNames|getAttributeNode|\\n   getAttributeNodeNS|getAttributeNS|getBoundingClientRect|getBoxQuads|\\n   getClientRects|getContext|getDestinationInsertionPoints|getElementById|\\n   getElementsByClassName|getElementsByName|getElementsByTagName|\\n   getElementsByTagNameNS|getItem|getNamedItem|getSelection|getStartDate|\\n   getVideoPlaybackQuality|has|hasAttribute|hasAttributeNS|hasAttributes|\\n   hasChildNodes|hasFeature|hasFocus|importNode|initEvent|insertAdjacentElement|\\n   insertAdjacentHTML|insertAdjacentText|insertBefore|insertCell|insertData|\\n   insertNode|insertRow|intersectsNode|isDefaultNamespace|isEqualNode|\\n   isPointInRange|isSameNode|item|key|keys|lastChild|load|lookupNamespaceURI|\\n   lookupPrefix|matches|move|moveAttribute|moveAttributeNode|moveChild|\\n   moveNamedItem|namedItem|nextNode|nextSibling|normalize|observe|open|\\n   parentNode|pause|play|postMessage|prepend|preventDefault|previousNode|\\n   previousSibling|probablySupportsContext|queryCommandEnabled|\\n   queryCommandIndeterm|queryCommandState|queryCommandSupported|queryCommandValue|\\n   querySelector|querySelectorAll|registerContentHandler|registerElement|\\n   registerProtocolHandler|releaseCapture|releaseEvents|remove|removeAttribute|\\n   removeAttributeNode|removeAttributeNS|removeChild|removeEventListener|\\n   removeItem|replace|replaceChild|replaceData|replaceWith|reportValidity|\\n   requestFullscreen|requestPointerLock|reset|scroll|scrollBy|scrollIntoView|\\n   scrollTo|seekToNextFrame|select|selectNode|selectNodeContents|set|setAttribute|\\n   setAttributeNode|setAttributeNodeNS|setAttributeNS|setCapture|\\n   setCustomValidity|setEnd|setEndAfter|setEndBefore|setItem|setNamedItem|\\n   setRangeText|setSelectionRange|setSinkId|setStart|setStartAfter|setStartBefore|\\n   slice|splitText|stepDown|stepUp|stopImmediatePropagation|stopPropagation|\\n   submit|substringData|supports|surroundContents|takeRecords|terminate|toBlob|\\n   toDataURL|toggle|toString|values|write|writeln\\n )\\n)(?=\\\\s*\\\\()\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"support.function.event-handler.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.function.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"support.function.dom.tsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"identifiers\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#object-identifiers\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:(\\\\.)\\\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*=\\\\s*(\\n  ((async\\\\s+)?(\\n    (function\\\\s*[(<*]) |\\n    (function\\\\s+) |\\n    ([_$[:alpha:]][_$[:alnum:]]*\\\\s*=>)\\n  )) |\\n  ((async\\\\s*)?(\\n    # sure shot arrow functions even if => is on new line\\n(\\n  [(]\\\\s*\\n  (\\n    ([)]\\\\s*:) |                                                                 # ():\\n    ((\\\\.\\\\.\\\\.\\\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\\\s*:)                                            # [(]param: | [(]...param:\\n  )\\n) |\\n(\\n  [<]\\\\s*[_$[:alpha:]][_$[:alnum:]]*\\\\s+extends\\\\s*[^=>]                                        # < typeparam extends\\n) |\\n# arrow function possible to detect only with => on same line\\n(\\n  (<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^<>=]|=[^<]|\\\\<\\\\s*[_$[:alpha:]\\\\{\\\\(\\\\[]([^=<>]|=[^<])+\\\\>)+>\\\\s*)?                                                           # typeparameters\\n  \\\\(\\\\s*([_$[:alpha:]\\\\{\\\\[]([^()]|\\\\((\\\\s*[^()]*)?\\\\))*)?\\\\)                          # parameteres\\n  (\\\\s*:\\\\s*([^<>\\\\(\\\\)]|\\\\<[^<>]+\\\\>|\\\\([^\\\\(\\\\)]+\\\\))+)?                                # return type\\n  \\\\s*=>                                                                         # arrow operator\\n)\\n  ))\\n))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.function.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.property.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\": \"(\\\\.)\\\\s*([_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.property.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"variable.other.constant.tsx\",\n                    \"match\": \"([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])\"\n                },\n                {\n                    \"name\": \"variable.other.readwrite.tsx\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"object-identifiers\": {\n            \"patterns\": [\n                {\n                    \"name\": \"support.class.tsx\",\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)(?=\\\\s*\\\\.\\\\s*prototype\\\\b(?!\\\\$))\"\n                },\n                {\n                    \"match\":\n                        \"(?x)(\\\\.)\\\\s*(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.constant.object.property.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.object.property.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)(?:\\n  ([[:upper:]][_$[:digit:][:upper:]]*) |\\n  ([_$[:alpha:]][_$[:alnum:]]*)\\n)(?=\\\\s*\\\\.\\\\s*[_$[:alpha:]][_$[:alnum:]]*)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"variable.other.constant.object.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"variable.other.object.tsx\"\n                        }\n                    }\n                }\n            ]\n        },\n        \"type-annotation\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.annotation.tsx\",\n                    \"begin\": \"(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.tsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=$|^|[,);\\\\}\\\\]]|//)|(?==[^>])|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.annotation.tsx\",\n                    \"begin\": \"(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.tsx\"\n                        }\n                    },\n                    \"end\":\n                        \"(?<![:|&])((?=[,);\\\\}\\\\]]|//)|(?==[^>])|(?=^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$))|((?<=[\\\\}>\\\\]\\\\)]|[_$[:alpha:]])\\\\s*(?=\\\\{)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.return.type.tsx\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])(?=$|^|[{};,]|//)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.return.type.tsx\",\n                    \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.operator.type.annotation.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<![:|&])((?=[{};,]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<=[:|&])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"arrow-return-type\": {\n            \"name\": \"meta.return.type.arrow.tsx\",\n            \"begin\": \"(?<=\\\\))\\\\s*(:)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"keyword.operator.type.annotation.tsx\"\n                }\n            },\n            \"end\":\n                \"(?==>|\\\\{|(^\\\\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\\\\s+))\",\n            \"patterns\": [\n                {\n                    \"begin\": \"(?<=[:])(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-parameters\": {\n            \"name\": \"meta.type.parameters.tsx\",\n            \"begin\": \"(<)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.begin.tsx\"\n                }\n            },\n            \"end\": \"(>)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.typeparameters.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"name\": \"storage.modifier.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(extends)\\\\b(?!\\\\$)\"\n                },\n                {\n                    \"name\": \"keyword.operator.assignment.tsx\",\n                    \"match\": \"\\\\=(?!>)\"\n                },\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#string\"\n                },\n                {\n                    \"include\": \"#numeric-literal\"\n                },\n                {\n                    \"include\": \"#type-primitive\"\n                },\n                {\n                    \"include\": \"#type-builtin-literals\"\n                },\n                {\n                    \"include\": \"#type-parameters\"\n                },\n                {\n                    \"include\": \"#type-tuple\"\n                },\n                {\n                    \"include\": \"#type-object\"\n                },\n                {\n                    \"include\": \"#type-operators\"\n                },\n                {\n                    \"include\": \"#type-fn-type-parameters\"\n                },\n                {\n                    \"include\": \"#type-paren-or-function-parameters\"\n                },\n                {\n                    \"include\": \"#type-function-return-type\"\n                },\n                {\n                    \"include\": \"#type-name\"\n                }\n            ]\n        },\n        \"type-primitive\": {\n            \"name\": \"support.type.primitive.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(string|number|boolean|symbol|any|void|never)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-builtin-literals\": {\n            \"name\": \"support.type.builtin.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\b(this|true|false|undefined|null|object)\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-tuple\": {\n            \"name\": \"meta.type.tuple.tsx\",\n            \"begin\": \"\\\\[\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                }\n            },\n            \"end\": \"\\\\]\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.square.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                }\n            ]\n        },\n        \"type-object\": {\n            \"name\": \"meta.object.type.tsx\",\n            \"begin\": \"\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.block.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"include\": \"#method-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-declaration\"\n                },\n                {\n                    \"include\": \"#indexer-mapped-type-declaration\"\n                },\n                {\n                    \"include\": \"#field-declaration\"\n                },\n                {\n                    \"include\": \"#type-annotation\"\n                },\n                {\n                    \"begin\": \"\\\\.\\\\.\\\\.\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.spread.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\}|;|,|$)|(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#punctuation-comma\"\n                },\n                {\n                    \"include\": \"#punctuation-semicolon\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-paren-or-function-parameters\": {\n            \"name\": \"meta.type.paren.cover.tsx\",\n            \"begin\": \"\\\\(\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.tsx\"\n                }\n            },\n            \"end\": \"\\\\)\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.brace.round.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#type\"\n                },\n                {\n                    \"include\": \"#function-parameters\"\n                }\n            ]\n        },\n        \"type-fn-type-parameters\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.constructor.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b(?=\\\\s*\\\\<)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.type.constructor.tsx\",\n                    \"begin\": \"(?<!\\\\.|\\\\$)\\\\b(new)\\\\b\\\\s*(?=\\\\()\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"keyword.control.new.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.tsx\",\n                    \"begin\":\n                        \"(?x)(\\n  (?=\\n    [(]\\\\s*(\\n      ([)]) |\\n      (\\\\.\\\\.\\\\.) |\\n      ([_$[:alnum:]]+\\\\s*(\\n        ([:,?=])|\\n        ([)]\\\\s*=>)\\n      ))\\n    )\\n  )\\n)\",\n                    \"end\": \"(?<=\\\\))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#function-parameters\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type\": {\n            \"patterns\": [\n                {\n                    \"name\": \"meta.type.function.return.tsx\",\n                    \"begin\": \"(=>)(?=\\\\s*\\\\S)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.function.arrow.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])(?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|$)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.type.function.return.tsx\",\n                    \"begin\": \"=>\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"storage.type.function.arrow.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<!=>)(?<![|&])((?=[,\\\\]\\\\)\\\\{\\\\}=;>]|//|^\\\\s*$)|((?<=\\\\S)(?=\\\\s*$)))\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-function-return-type-core\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"type-function-return-type-core\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#comment\"\n                },\n                {\n                    \"begin\": \"(?<==>)(?=\\\\s*\\\\{)\",\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#type-predicate-operator\"\n                },\n                {\n                    \"include\": \"#type\"\n                }\n            ]\n        },\n        \"type-operators\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#typeof-operator\"\n                },\n                {\n                    \"begin\": \"([&|])(?=\\\\s*\\\\{)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.tsx\"\n                        }\n                    },\n                    \"end\": \"(?<=\\\\})\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#type-object\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"[&|]\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"keyword.operator.type.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\S)\"\n                },\n                {\n                    \"name\": \"keyword.operator.expression.keyof.tsx\",\n                    \"match\": \"(?<!\\\\.|\\\\$)\\\\bkeyof\\\\b(?!\\\\$|\\\\.)\"\n                }\n            ]\n        },\n        \"type-predicate-operator\": {\n            \"name\": \"keyword.operator.expression.is.tsx\",\n            \"match\": \"(?<!\\\\.|\\\\$)\\\\bis\\\\b(?!\\\\$|\\\\.)\"\n        },\n        \"type-name\": {\n            \"patterns\": [\n                {\n                    \"match\": \"([_$[:alpha:]][_$[:alnum:]]*)\\\\s*(\\\\.)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.module.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.accessor.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.tsx\",\n                    \"match\": \"[_$[:alpha:]][_$[:alnum:]]*\"\n                }\n            ]\n        },\n        \"punctuation-comma\": {\n            \"name\": \"punctuation.separator.comma.tsx\",\n            \"match\": \",\"\n        },\n        \"punctuation-semicolon\": {\n            \"name\": \"punctuation.terminator.statement.tsx\",\n            \"match\": \";\"\n        },\n        \"punctuation-accessor\": {\n            \"name\": \"punctuation.accessor.tsx\",\n            \"match\": \"\\\\.\"\n        },\n        \"string\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#qstring-single\"\n                },\n                {\n                    \"include\": \"#qstring-double\"\n                }\n            ]\n        },\n        \"qstring-double\": {\n            \"name\": \"string.quoted.double.tsx\",\n            \"begin\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.tsx\"\n                }\n            },\n            \"end\": \"(\\\")|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"qstring-single\": {\n            \"name\": \"string.quoted.single.tsx\",\n            \"begin\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.tsx\"\n                }\n            },\n            \"end\": \"(\\\\')|((?:[^\\\\\\\\\\\\n])$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.string.end.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"invalid.illegal.newline.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"string-character-escape\": {\n            \"name\": \"constant.character.escape.tsx\",\n            \"match\": \"\\\\\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)\"\n        },\n        \"template\": {\n            \"name\": \"string.template.tsx\",\n            \"begin\": \"([_$[:alpha:]][_$[:alnum:]]*)?(`)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"entity.name.function.tagged-template.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.string.template.begin.tsx\"\n                }\n            },\n            \"end\": \"`\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.template.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#template-substitution-element\"\n                },\n                {\n                    \"include\": \"#string-character-escape\"\n                }\n            ]\n        },\n        \"template-substitution-element\": {\n            \"name\": \"meta.template.expression.tsx\",\n            \"begin\": \"\\\\$\\\\{\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.begin.tsx\"\n                }\n            },\n            \"end\": \"\\\\}\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.template-expression.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ],\n            \"contentName\": \"meta.embedded.line.tsx\"\n        },\n        \"regex\": {\n            \"patterns\": [\n                {\n                    \"name\": \"string.regexp.tsx\",\n                    \"begin\":\n                        \"(?<=[=(:,\\\\[?+!]|return|case|=>|&&|\\\\|\\\\||\\\\*\\\\/)\\\\s*(\\\\/)(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.begin.tsx\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"string.regexp.tsx\",\n                    \"begin\":\n                        \"(?<![_$[:alnum:])])\\\\/(?![\\\\/*])(?=(?:[^\\\\/\\\\\\\\\\\\[]|\\\\\\\\.|\\\\[([^\\\\]\\\\\\\\]|\\\\\\\\.)+\\\\])+\\\\/(?![\\\\/*])[gimuy]*(?!\\\\s*[a-zA-Z0-9_$]))\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.tsx\"\n                        }\n                    },\n                    \"end\": \"(/)([gimuy]*)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.other.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"regexp\": {\n            \"patterns\": [\n                {\n                    \"name\": \"keyword.control.anchor.regexp\",\n                    \"match\": \"\\\\\\\\[bB]|\\\\^|\\\\$\"\n                },\n                {\n                    \"name\": \"keyword.other.back-reference.regexp\",\n                    \"match\": \"\\\\\\\\[1-9]\\\\d*\"\n                },\n                {\n                    \"name\": \"keyword.operator.quantifier.regexp\",\n                    \"match\": \"[?+*]|\\\\{(\\\\d+,\\\\d+|\\\\d+,|,\\\\d+|\\\\d+)\\\\}\\\\??\"\n                },\n                {\n                    \"name\": \"keyword.operator.or.regexp\",\n                    \"match\": \"\\\\|\"\n                },\n                {\n                    \"name\": \"meta.group.assertion.regexp\",\n                    \"begin\": \"(\\\\()((\\\\?=)|(\\\\?!))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.group.assertion.regexp\"\n                        },\n                        \"3\": {\n                            \"name\": \"meta.assertion.look-ahead.regexp\"\n                        },\n                        \"4\": {\n                            \"name\": \"meta.assertion.negative-look-ahead.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\))\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"meta.group.regexp\",\n                    \"begin\": \"\\\\((\\\\?:)?\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.group.no-capture.regexp\"\n                        }\n                    },\n                    \"end\": \"\\\\)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.group.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#regexp\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"constant.other.character-class.set.regexp\",\n                    \"begin\": \"(\\\\[)(\\\\^)?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        },\n                        \"2\": {\n                            \"name\": \"keyword.operator.negation.regexp\"\n                        }\n                    },\n                    \"end\": \"(\\\\])\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.character-class.regexp\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"constant.other.character-class.range.regexp\",\n                            \"match\":\n                                \"(?:.|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\\\\-(?:[^\\\\]\\\\\\\\]|(\\\\\\\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\\\\\\\c[A-Z])|(\\\\\\\\.))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"2\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"3\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                },\n                                \"4\": {\n                                    \"name\": \"constant.character.numeric.regexp\"\n                                },\n                                \"5\": {\n                                    \"name\": \"constant.character.control.regexp\"\n                                },\n                                \"6\": {\n                                    \"name\": \"constant.character.escape.backslash.regexp\"\n                                }\n                            }\n                        },\n                        {\n                            \"include\": \"#regex-character-class\"\n                        }\n                    ]\n                },\n                {\n                    \"include\": \"#regex-character-class\"\n                }\n            ]\n        },\n        \"regex-character-class\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.character-class.regexp\",\n                    \"match\": \"\\\\\\\\[wWsSdDtrnvf]|\\\\.\"\n                },\n                {\n                    \"name\": \"constant.character.numeric.regexp\",\n                    \"match\": \"\\\\\\\\([0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})\"\n                },\n                {\n                    \"name\": \"constant.character.control.regexp\",\n                    \"match\": \"\\\\\\\\c[A-Z]\"\n                },\n                {\n                    \"name\": \"constant.character.escape.backslash.regexp\",\n                    \"match\": \"\\\\\\\\.\"\n                }\n            ]\n        },\n        \"comment\": {\n            \"patterns\": [\n                {\n                    \"name\": \"comment.block.documentation.tsx\",\n                    \"begin\": \"/\\\\*\\\\*(?!/)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#docblock\"\n                        }\n                    ]\n                },\n                {\n                    \"name\": \"comment.block.tsx\",\n                    \"begin\": \"(/\\\\*)(?:\\\\s*((@)internal)(?=\\\\s|(\\\\*/)))?\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.comment.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.internaldeclaration.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.tsx\"\n                        }\n                    },\n                    \"end\": \"\\\\*/\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.comment.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"(^[ \\\\t]+)?((//)(?:\\\\s*((@)internal)(?=\\\\s|$))?)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.whitespace.comment.leading.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"comment.line.double-slash.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.comment.tsx\"\n                        },\n                        \"4\": {\n                            \"name\": \"storage.type.internaldeclaration.tsx\"\n                        },\n                        \"5\": {\n                            \"name\": \"punctuation.decorator.internaldeclaration.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=^)\",\n                    \"contentName\": \"comment.line.double-slash.tsx\"\n                }\n            ]\n        },\n        \"directives\": {\n            \"name\": \"comment.line.triple-slash.directive.tsx\",\n            \"begin\":\n                \"^(///)\\\\s*(?=<(reference|amd-dependency|amd-module)(\\\\s+(path|types|no-default-lib|name)\\\\s*=\\\\s*((\\\\'([^\\\\'\\\\\\\\]|\\\\\\\\\\\\'|\\\\\\\\)*\\\\')|(\\\\\\\"([^\\\\\\\"\\\\\\\\]|\\\\\\\\\\\\\\\"|\\\\\\\\)*\\\\\\\")))+\\\\s*/>\\\\s*$)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.comment.tsx\"\n                }\n            },\n            \"end\": \"(?=^)\",\n            \"patterns\": [\n                {\n                    \"name\": \"meta.tag.tsx\",\n                    \"begin\": \"(<)(reference|amd-dependency|amd-module)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.directive.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.directive.tsx\"\n                        }\n                    },\n                    \"end\": \"/>\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.tag.directive.tsx\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"name\": \"entity.other.attribute-name.directive.tsx\",\n                            \"match\": \"path|types|no-default-lib|name\"\n                        },\n                        {\n                            \"name\": \"keyword.operator.assignment.tsx\",\n                            \"match\": \"=\"\n                        },\n                        {\n                            \"include\": \"#string\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"docblock\": {\n            \"patterns\": [\n                {\n                    \"match\": \"(?x)\\n((@)(?:access|api))\\n\\\\s+\\n(private|protected|public)\\n\\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.access-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)author)\\n\\\\s+\\n(\\n  [^@\\\\s<>*/]\\n  (?:[^@<>*/]|\\\\*[^/])*\\n)\\n(?:\\n  \\\\s*\\n  (<)\\n  ([^>\\\\s]+)\\n  (>)\\n)?\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"constant.other.email.link.underline.jsdoc\"\n                        },\n                        \"6\": {\n                            \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)borrows) \\\\s+\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <that namepath>\\n\\\\s+ (as) \\\\s+              # as\\n((?:[^@\\\\s*/]|\\\\*[^/])+)    # <this namepath>\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"keyword.operator.control.jsdoc\"\n                        },\n                        \"5\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"meta.example.jsdoc\",\n                    \"begin\": \"((@)example)\\\\s+\",\n                    \"end\": \"(?=@|\\\\*/)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"^\\\\s\\\\*\\\\s+\"\n                        },\n                        {\n                            \"contentName\": \"constant.other.description.jsdoc\",\n                            \"begin\": \"\\\\G(<)caption(>)\",\n                            \"beginCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            },\n                            \"end\": \"(</)caption(>)|(?=\\\\*/)\",\n                            \"endCaptures\": {\n                                \"0\": {\n                                    \"name\": \"entity.name.tag.inline.jsdoc\"\n                                },\n                                \"1\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.begin.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.definition.bracket.angle.end.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"[^\\\\s@*](?:[^*]|\\\\*[^/])*\",\n                            \"captures\": {\n                                \"0\": {\n                                    \"name\": \"source.embedded.tsx\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x) ((@)kind) \\\\s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"constant.language.symbol-type.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)see)\\n\\\\s+\\n(?:\\n  # URL\\n  (\\n    (?=https?://)\\n    (?:[^\\\\s*]|\\\\*[^/])+\\n  )\\n  |\\n  # JSDoc namepath\\n  (\\n    (?!\\n      # Avoid matching bare URIs (also acceptable as links)\\n      https?://\\n      |\\n      # Avoid matching {@inline tags}; we match those below\\n      (?:\\\\[[^\\\\[\\\\]]*\\\\])? # Possible description [preceding]{@tag}\\n      {@(?:link|linkcode|linkplain|tutorial)\\\\b\\n    )\\n    # Matched namepath\\n    (?:[^@\\\\s*/]|\\\\*[^/])+\\n  )\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.link.underline.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n((@)template)\\n\\\\s+\\n# One or more valid identifiers\\n(\\n  [A-Za-z_$]         # First character: non-numeric word character\\n  [\\\\w$.\\\\[\\\\]]*        # Rest of identifier\\n  (?:                # Possible list of additional identifiers\\n    \\\\s* , \\\\s*\\n    [A-Za-z_$]\\n    [\\\\w$.\\\\[\\\\]]*\\n  )*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:arg|argument|const|constant|member|namespace|param|var)\\n)\\n\\\\s+\\n(\\n  [A-Za-z_$]\\n  [\\\\w$.\\\\[\\\\]]*\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"begin\": \"((@)typedef)\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"entity.name.type.instance.jsdoc\",\n                            \"match\": \"(?:[^@\\\\s*/]|\\\\*[^/])+\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\": \"([A-Za-z_$][\\\\w$.\\\\[\\\\]]*)\"\n                        },\n                        {\n                            \"name\": \"variable.other.jsdoc\",\n                            \"match\":\n                                \"(?x)\\n(\\\\[)\\\\s*\\n[\\\\w$]+\\n(?:\\n  (?:\\\\[\\\\])?                                        # Foo[ ].bar properties within an array\\n  \\\\.                                                # Foo.Bar namespaced parameter\\n  [\\\\w$]+\\n)*\\n(?:\\n  \\\\s*\\n  (=)                                                # [foo=bar] Default parameter value\\n  \\\\s*\\n  (\\n    # The inner regexes are to stop the match early at */ and to not stop at escaped quotes\\n    (?>\\n      \\\"(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!\\\"))|[^*\\\\\\\\])*?\\\" |                      # [foo=\\\"bar\\\"] Double-quoted\\n      '(?:(?:\\\\*(?!/))|(?:\\\\\\\\(?!'))|[^*\\\\\\\\])*?' |                      # [foo='bar'] Single-quoted\\n      \\\\[ (?:(?:\\\\*(?!/))|[^*])*? \\\\] |                                # [foo=[1,2]] Array literal\\n      (?:(?:\\\\*(?!/))|\\\\s(?!\\\\s*\\\\])|\\\\[.*?(?:\\\\]|(?=\\\\*/))|[^*\\\\s\\\\[\\\\]])*   # Everything else\\n    )*\\n  )\\n)?\\n\\\\s*(?:(\\\\])((?:[^*\\\\s]|\\\\*[^\\\\s/])+)?|(?=\\\\*/))\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.begin.bracket.square.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"keyword.operator.assignment.jsdoc\"\n                                },\n                                \"3\": {\n                                    \"name\": \"source.embedded.tsx\"\n                                },\n                                \"4\": {\n                                    \"name\":\n                                        \"punctuation.definition.optional-value.end.bracket.square.jsdoc\"\n                                },\n                                \"5\": {\n                                    \"name\": \"invalid.illegal.syntax.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                },\n                {\n                    \"begin\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:define|enum|exception|export|extends|lends|implements|modifies\\n  |namespace|private|protected|returns?|suppress|this|throws|type\\n  |yields?)\\n)\\n\\\\s+(?={)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(?=\\\\s|\\\\*/|[^{}\\\\[\\\\]A-Za-z_$])\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsdoctype\"\n                        }\n                    ]\n                },\n                {\n                    \"match\":\n                        \"(?x)\\n(\\n  (@)\\n  (?:alias|augments|callback|constructs|emits|event|fires|exports?\\n  |extends|external|function|func|host|lends|listens|interface|memberof!?\\n  |method|module|mixes|mixin|name|requires|see|this|typedef|uses)\\n)\\n\\\\s+\\n(\\n  (?:\\n    [^{}@\\\\s*] | \\\\*[^/]\\n  )+\\n)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"contentName\": \"variable.other.jsdoc\",\n                    \"begin\": \"((@)(?:default(?:value)?|license|version))\\\\s+(([''\\\"]))\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"4\": {\n                            \"name\": \"punctuation.definition.string.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"(\\\\3)|(?=$|\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.string.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"match\":\n                        \"((@)(?:default(?:value)?|license|tutorial|variation|version))\\\\s+([^\\\\s*]+)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"variable.other.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"storage.type.class.jsdoc\",\n                    \"match\":\n                        \"(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \\\\b\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.block.tag.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"include\": \"#inline-tags\"\n                }\n            ]\n        },\n        \"brackets\": {\n            \"patterns\": [\n                {\n                    \"begin\": \"{\",\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"\\\\[\",\n                    \"end\": \"\\\\]|(?=\\\\*/)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"inline-tags\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.other.description.jsdoc\",\n                    \"match\": \"(\\\\[)[^\\\\]]+(\\\\])(?={@(?:link|linkcode|linkplain|tutorial))\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.square.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.square.end.jsdoc\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"({)((@)(?:link(?:code|plain)?|tutorial))\\\\s*\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"storage.type.class.jsdoc\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.inline.tag.jsdoc\"\n                        }\n                    },\n                    \"end\": \"}|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"match\": \"\\\\G((?=https?://)(?:[^|}\\\\s*]|\\\\*[/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.link.underline.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        },\n                        {\n                            \"match\": \"\\\\G((?:[^{}@\\\\s|*]|\\\\*[^/])+)(\\\\|)?\",\n                            \"captures\": {\n                                \"1\": {\n                                    \"name\": \"variable.other.description.jsdoc\"\n                                },\n                                \"2\": {\n                                    \"name\": \"punctuation.separator.pipe.jsdoc\"\n                                }\n                            }\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsdoctype\": {\n            \"patterns\": [\n                {\n                    \"name\": \"invalid.illegal.type.jsdoc\",\n                    \"match\": \"\\\\G{(?:[^}*]|\\\\*[^/}])+$\"\n                },\n                {\n                    \"contentName\": \"entity.name.type.instance.jsdoc\",\n                    \"begin\": \"\\\\G({)\",\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.bracket.curly.begin.jsdoc\"\n                        }\n                    },\n                    \"end\": \"((}))\\\\s*|(?=\\\\*/)\",\n                    \"endCaptures\": {\n                        \"1\": {\n                            \"name\": \"entity.name.type.instance.jsdoc\"\n                        },\n                        \"2\": {\n                            \"name\": \"punctuation.definition.bracket.curly.end.jsdoc\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#brackets\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsx\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes-in-expression\"\n                },\n                {\n                    \"include\": \"#jsx-tag-in-expression\"\n                }\n            ]\n        },\n        \"jsx-tag-without-attributes-in-expression\": {\n            \"begin\":\n                \"(?x)\\n  (?<=[({\\\\[,?=>:*]|&&|\\\\|\\\\||\\\\?|\\\\Wreturn|^return|\\\\Wdefault|^)\\\\s*\\n  (?=(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>))\",\n            \"end\": \"(?!\\\\s*(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>))\",\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes\"\n                }\n            ]\n        },\n        \"jsx-tag-without-attributes\": {\n            \"name\": \"meta.tag.without-attributes.tsx\",\n            \"begin\": \"(<)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>)\",\n            \"end\": \"(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))?\\\\s*(>)\",\n            \"beginCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"support.class.component.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.tag.end.tsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"entity.name.tag.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"support.class.component.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"punctuation.definition.tag.end.tsx\"\n                }\n            },\n            \"contentName\": \"meta.jsx.children.tsx\",\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-children\"\n                }\n            ]\n        },\n        \"jsx-tag-in-expression\": {\n            \"begin\":\n                \"(?x)\\n  (?<=[({\\\\[,?=>:*]|&&|\\\\|\\\\||\\\\?|\\\\Wreturn|^return|\\\\Wdefault|^)\\\\s*\\n  (?!<\\\\s*[_$[:alpha:]][_$[:alnum:]]*((\\\\s+extends\\\\s+[^=>])|,)) # look ahead is not type parameter of arrow\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(/>)|(?:(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\\\s*(>))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.tag.tsx\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.tag.begin.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"support.class.component.tsx\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.tag.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag\"\n                }\n            ]\n        },\n        \"jsx-child-tag\": {\n            \"begin\":\n                \"(?x)\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(/>)|(?:(</)\\\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\\\s*(>))\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"meta.tag.tsx\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.tsx\"\n                },\n                \"2\": {\n                    \"name\": \"punctuation.definition.tag.begin.tsx\"\n                },\n                \"3\": {\n                    \"name\": \"entity.name.tag.tsx\"\n                },\n                \"4\": {\n                    \"name\": \"support.class.component.tsx\"\n                },\n                \"5\": {\n                    \"name\": \"punctuation.definition.tag.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag\"\n                }\n            ]\n        },\n        \"jsx-tag\": {\n            \"name\": \"meta.tag.tsx\",\n            \"begin\":\n                \"(?x)\\n  (?=(<)\\\\s*\\n  ([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>))\",\n            \"end\": \"(?=(/>)|(?:(</)\\\\s*([_$a-zA-Z][-$\\\\w.]*(?<!\\\\.|-))\\\\s*(>)))\",\n            \"patterns\": [\n                {\n                    \"begin\":\n                        \"(?x)\\n  (<)\\\\s*\\n  ((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\\\w.]*))(?<!\\\\.|-))\\n  (?=\\\\s+(?!\\\\?)|/?>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.begin.tsx\"\n                        },\n                        \"2\": {\n                            \"name\": \"entity.name.tag.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"support.class.component.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=[/]?>)\",\n                    \"contentName\": \"meta.tag.attributes.tsx\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#comment\"\n                        },\n                        {\n                            \"include\": \"#jsx-tag-attributes\"\n                        },\n                        {\n                            \"include\": \"#jsx-tag-attributes-illegal\"\n                        }\n                    ]\n                },\n                {\n                    \"begin\": \"(>)\",\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.tsx\"\n                        }\n                    },\n                    \"end\": \"(?=</)\",\n                    \"contentName\": \"meta.jsx.children.tsx\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"#jsx-children\"\n                        }\n                    ]\n                }\n            ]\n        },\n        \"jsx-children\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-without-attributes\"\n                },\n                {\n                    \"include\": \"#jsx-child-tag\"\n                },\n                {\n                    \"include\": \"#jsx-evaluated-code\"\n                },\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-evaluated-code\": {\n            \"name\": \"meta.embedded.expression.tsx\",\n            \"begin\": \"\\\\{\",\n            \"end\": \"\\\\}\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.begin.tsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.section.embedded.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#expression\"\n                }\n            ]\n        },\n        \"jsx-entities\": {\n            \"patterns\": [\n                {\n                    \"name\": \"constant.character.entity.tsx\",\n                    \"match\": \"(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)\",\n                    \"captures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.tsx\"\n                        },\n                        \"3\": {\n                            \"name\": \"punctuation.definition.entity.tsx\"\n                        }\n                    }\n                },\n                {\n                    \"name\": \"invalid.illegal.bad-ampersand.tsx\",\n                    \"match\": \"&\"\n                }\n            ]\n        },\n        \"jsx-tag-attributes\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-tag-attribute-name\"\n                },\n                {\n                    \"include\": \"#jsx-tag-attribute-assignment\"\n                },\n                {\n                    \"include\": \"#jsx-string-double-quoted\"\n                },\n                {\n                    \"include\": \"#jsx-string-single-quoted\"\n                },\n                {\n                    \"include\": \"#jsx-evaluated-code\"\n                }\n            ]\n        },\n        \"jsx-tag-attribute-name\": {\n            \"match\": \"(?x)\\n  \\\\s*\\n  ([_$a-zA-Z][-$\\\\w]*)\\n  (?=\\\\s|=|/?>|/\\\\*|//)\",\n            \"captures\": {\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.tsx\"\n                }\n            }\n        },\n        \"jsx-tag-attribute-assignment\": {\n            \"name\": \"keyword.operator.assignment.tsx\",\n            \"match\": \"=(?=\\\\s*(?:'|\\\"|{|/\\\\*|//|\\\\n))\"\n        },\n        \"jsx-string-double-quoted\": {\n            \"name\": \"string.quoted.double.tsx\",\n            \"begin\": \"\\\"\",\n            \"end\": \"\\\"\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.tsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-string-single-quoted\": {\n            \"name\": \"string.quoted.single.tsx\",\n            \"begin\": \"'\",\n            \"end\": \"'\",\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.tsx\"\n                }\n            },\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.tsx\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#jsx-entities\"\n                }\n            ]\n        },\n        \"jsx-tag-attributes-illegal\": {\n            \"name\": \"invalid.illegal.attribute.tsx\",\n            \"match\": \"\\\\S+\"\n        }\n    }\n}\n"
  },
  {
    "path": "extensions/vue/syntaxes/vue.json",
    "content": "{\n    \"uuid\": \"5512c10d-4cc5-434c-b8fc-53b912f55ab3\",\n    \"repository\": {\n        \"entities\": {\n            \"patterns\": [\n                {\n                    \"captures\": {\n                        \"3\": {\n                            \"name\": \"punctuation.definition.entity.html\"\n                        },\n                        \"1\": {\n                            \"name\": \"punctuation.definition.entity.html\"\n                        }\n                    },\n                    \"match\": \"(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)\",\n                    \"name\": \"constant.character.entity.html\"\n                },\n                {\n                    \"match\": \"&\",\n                    \"name\": \"invalid.illegal.bad-ampersand.html\"\n                }\n            ]\n        },\n        \"string-single-quoted\": {\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.html\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#vue-interpolations\"\n                },\n                {\n                    \"include\": \"#entities\"\n                }\n            ],\n            \"begin\": \"'\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.html\"\n                }\n            },\n            \"end\": \"'\",\n            \"name\": \"string.quoted.single.html\"\n        },\n        \"string-double-quoted\": {\n            \"beginCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.begin.html\"\n                }\n            },\n            \"patterns\": [\n                {\n                    \"include\": \"#vue-interpolations\"\n                },\n                {\n                    \"include\": \"#entities\"\n                }\n            ],\n            \"begin\": \"\\\"\",\n            \"endCaptures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.string.end.html\"\n                }\n            },\n            \"end\": \"\\\"\",\n            \"name\": \"string.quoted.double.html\"\n        },\n        \"vue-interpolations\": {\n            \"patterns\": [\n                {\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.generic.begin.html\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.js\"\n                        }\n                    ],\n                    \"begin\": \"\\\\{\\\\{\\\\{?\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.generic.end.html\"\n                        }\n                    },\n                    \"end\": \"\\\\}\\\\}\\\\}?\",\n                    \"name\": \"expression.embbeded.vue\"\n                }\n            ]\n        },\n        \"vue-directives\": {\n            \"captures\": {\n                \"2\": {\n                    \"name\": \"punctuation.separator.key-value.html\"\n                },\n                \"3\": {\n                    \"name\": \"entity.other.attribute-name.html\"\n                },\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.html\"\n                },\n                \"6\": {\n                    \"name\": \"punctuation.separator.key-value.html\"\n                },\n                \"4\": {\n                    \"name\": \"entity.other.attribute-name.html\"\n                },\n                \"5\": {\n                    \"name\": \"entity.other.attribute-name.html\"\n                }\n            },\n            \"begin\":\n                \"(?:\\\\b(v-)|(:|@))([a-zA-Z\\\\-_]+)(?:\\\\:([a-zA-Z\\\\-_]+))?(?:\\\\.([a-zA-Z\\\\-_]+))*\\\\s*(=)\",\n            \"end\": \"(?<='|\\\")\",\n            \"name\": \"meta.directive.vue\",\n            \"patterns\": [\n                {\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.html\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.js\"\n                        }\n                    ],\n                    \"begin\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.html\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"name\": \"source.directive.vue\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.html\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.js\"\n                        }\n                    ],\n                    \"begin\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.html\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"name\": \"source.directive.vue\"\n                }\n            ]\n        },\n        \"tag-generic-attribute\": {\n            \"match\": \"\\\\b([a-zA-Z\\\\-:_]+)\",\n            \"name\": \"entity.other.attribute-name.html\"\n        },\n        \"tag-id-attribute\": {\n            \"captures\": {\n                \"2\": {\n                    \"name\": \"punctuation.separator.key-value.html\"\n                },\n                \"1\": {\n                    \"name\": \"entity.other.attribute-name.id.html\"\n                }\n            },\n            \"begin\": \"\\\\b(id)\\\\b\\\\s*(=)\",\n            \"end\": \"(?<='|\\\")\",\n            \"name\": \"meta.attribute-with-value.id.html\",\n            \"patterns\": [\n                {\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.html\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#vue-interpolations\"\n                        },\n                        {\n                            \"include\": \"#entities\"\n                        }\n                    ],\n                    \"begin\": \"\\\"\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.html\"\n                        }\n                    },\n                    \"end\": \"\\\"\",\n                    \"name\": \"string.quoted.double.html\",\n                    \"contentName\": \"meta.toc-list.id.html\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.begin.html\"\n                        }\n                    },\n                    \"patterns\": [\n                        {\n                            \"include\": \"#vue-interpolations\"\n                        },\n                        {\n                            \"include\": \"#entities\"\n                        }\n                    ],\n                    \"begin\": \"'\",\n                    \"endCaptures\": {\n                        \"0\": {\n                            \"name\": \"punctuation.definition.string.end.html\"\n                        }\n                    },\n                    \"end\": \"'\",\n                    \"name\": \"string.quoted.single.html\",\n                    \"contentName\": \"meta.toc-list.id.html\"\n                }\n            ]\n        },\n        \"tag-stuff\": {\n            \"patterns\": [\n                {\n                    \"include\": \"#vue-directives\"\n                },\n                {\n                    \"include\": \"#tag-id-attribute\"\n                },\n                {\n                    \"include\": \"#tag-generic-attribute\"\n                },\n                {\n                    \"include\": \"#string-double-quoted\"\n                },\n                {\n                    \"include\": \"#string-single-quoted\"\n                }\n            ]\n        }\n    },\n    \"patterns\": [\n        {\n            \"captures\": {\n                \"0\": {\n                    \"name\": \"punctuation.definition.comment.html\"\n                }\n            },\n            \"begin\": \"<!--\",\n            \"end\": \"--\\\\s*>\",\n            \"name\": \"comment.block.html\",\n            \"patterns\": [\n                {\n                    \"match\": \"--\",\n                    \"name\": \"invalid.illegal.bad-comments-or-CDATA.html\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(template)\\\\b(?=[^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                }\n            },\n            \"end\": \"(/>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(template)(?=[^>]*>[^/>]*</template>)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(template)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</template>)\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\":\n                \"(<)(template)\\\\b(?=[^>]*lang=('jade'|\\\"jade\\\"|'pug'|\\\"pug\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(template)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</template>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.pug\"\n                        }\n                    ],\n                    \"contentName\": \"text.pug\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(template)\\\\b(?=[^>]*lang=('haml'|\\\"haml\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(template)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</template>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.haml\"\n                        }\n                    ],\n                    \"contentName\": \"text.haml\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(template)\\\\b(?=[^>]*lang=('slm'|\\\"slm\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(template)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</template>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.pug.slm\"\n                        }\n                    ],\n                    \"contentName\": \"text.pug.slm\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(template)(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.template.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(template)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</template>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"text.html.vue-html\"\n                        }\n                    ],\n                    \"contentName\": \"text.html.vue-html\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)\\\\b(?=[^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                }\n            },\n            \"end\": \"(/>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)(?=[^>]*>[^/>]*</style>)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)\\\\b(?=[^>]*lang=('sass'|\\\"sass\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.sass\"\n                        }\n                    ],\n                    \"contentName\": \"source.sass\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)\\\\b(?=[^>]*lang=('scss'|\\\"scss\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.css.scss\"\n                        }\n                    ],\n                    \"contentName\": \"source.css.scss\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)\\\\b(?=[^>]*lang=('less'|\\\"less\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.css.less\"\n                        }\n                    ],\n                    \"contentName\": \"source.css.less\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)\\\\b(?=[^>]*lang=('stylus'|\\\"stylus\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.stylus\"\n                        }\n                    ],\n                    \"contentName\": \"source.stylus\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)\\\\b(?=[^>]*lang=('postcss'|\\\"postcss\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.css.postcss\"\n                        }\n                    ],\n                    \"contentName\": \"source.css.postcss\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(style)(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.style.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(style)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</style>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.css\"\n                        }\n                    ],\n                    \"contentName\": \"source.css\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(script)\\\\b(?=[^>]*/>$)\",\n            \"endCaptures\": {\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                }\n            },\n            \"end\": \"(/>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(script)(?=[^>]*>[^/>]*</script>)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(script)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</script>)\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(script)\\\\b(?=[^>]*lang=('ts'|\\\"ts\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(script)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</script>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.ts\"\n                        }\n                    ],\n                    \"contentName\": \"source.ts\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(script)\\\\b(?=[^>]*lang=('coffee'|\\\"coffee\\\"))(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(script)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</script>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.coffee\"\n                        }\n                    ],\n                    \"contentName\": \"source.coffee\"\n                }\n            ]\n        },\n        {\n            \"beginCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"begin\": \"(<)(script)(?![^/>]*/>\\\\s*$)\",\n            \"endCaptures\": {\n                \"2\": {\n                    \"name\": \"entity.name.tag.script.html\"\n                },\n                \"3\": {\n                    \"name\": \"punctuation.definition.tag.end.html\"\n                },\n                \"1\": {\n                    \"name\": \"punctuation.definition.tag.begin.html\"\n                }\n            },\n            \"end\": \"(</)(script)(>)\",\n            \"patterns\": [\n                {\n                    \"include\": \"#tag-stuff\"\n                },\n                {\n                    \"beginCaptures\": {\n                        \"1\": {\n                            \"name\": \"punctuation.definition.tag.end.html\"\n                        }\n                    },\n                    \"begin\": \"(>)\",\n                    \"end\": \"(?=</script>)\",\n                    \"patterns\": [\n                        {\n                            \"include\": \"source.js\"\n                        }\n                    ],\n                    \"contentName\": \"source.js\"\n                }\n            ]\n        }\n    ],\n    \"fileTypes\": [\"vue\"],\n    \"name\": \"Vue Component\",\n    \"scopeName\": \"source.vue\"\n}\n"
  },
  {
    "path": "font-awesome/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.7.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n.fa {\n  display: inline-block;\n  font: normal normal normal 14px/1 FontAwesome;\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n/* makes the font 33% larger relative to the icon container */\n.fa-lg {\n  font-size: 1.33333333em;\n  line-height: 0.75em;\n  vertical-align: -15%;\n}\n.fa-2x {\n  font-size: 2em;\n}\n.fa-3x {\n  font-size: 3em;\n}\n.fa-4x {\n  font-size: 4em;\n}\n.fa-5x {\n  font-size: 5em;\n}\n.fa-fw {\n  width: 1.28571429em;\n  text-align: center;\n}\n.fa-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.fa-ul > li {\n  position: relative;\n}\n.fa-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n.fa-li.fa-lg {\n  left: -1.85714286em;\n}\n.fa-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eeeeee;\n  border-radius: .1em;\n}\n.fa-pull-left {\n  float: left;\n}\n.fa-pull-right {\n  float: right;\n}\n.fa.fa-pull-left {\n  margin-right: .3em;\n}\n.fa.fa-pull-right {\n  margin-left: .3em;\n}\n/* Deprecated as of 4.4.0 */\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n.fa.pull-left {\n  margin-right: .3em;\n}\n.fa.pull-right {\n  margin-left: .3em;\n}\n.fa-spin {\n  -webkit-animation: fa-spin 2s infinite linear;\n  animation: fa-spin 2s infinite linear;\n}\n.fa-pulse {\n  -webkit-animation: fa-spin 1s infinite steps(8);\n  animation: fa-spin 1s infinite steps(8);\n}\n@-webkit-keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n.fa-rotate-90 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)\";\n  -webkit-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  transform: rotate(90deg);\n}\n.fa-rotate-180 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)\";\n  -webkit-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n.fa-rotate-270 {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)\";\n  -webkit-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)\";\n  -webkit-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n  -ms-filter: \"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)\";\n  -webkit-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical {\n  filter: none;\n}\n.fa-stack {\n  position: relative;\n  display: inline-block;\n  width: 2em;\n  height: 2em;\n  line-height: 2em;\n  vertical-align: middle;\n}\n.fa-stack-1x,\n.fa-stack-2x {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  text-align: center;\n}\n.fa-stack-1x {\n  line-height: inherit;\n}\n.fa-stack-2x {\n  font-size: 2em;\n}\n.fa-inverse {\n  color: #ffffff;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.fa-glass:before {\n  content: \"\\f000\";\n}\n.fa-music:before {\n  content: \"\\f001\";\n}\n.fa-search:before {\n  content: \"\\f002\";\n}\n.fa-envelope-o:before {\n  content: \"\\f003\";\n}\n.fa-heart:before {\n  content: \"\\f004\";\n}\n.fa-star:before {\n  content: \"\\f005\";\n}\n.fa-star-o:before {\n  content: \"\\f006\";\n}\n.fa-user:before {\n  content: \"\\f007\";\n}\n.fa-film:before {\n  content: \"\\f008\";\n}\n.fa-th-large:before {\n  content: \"\\f009\";\n}\n.fa-th:before {\n  content: \"\\f00a\";\n}\n.fa-th-list:before {\n  content: \"\\f00b\";\n}\n.fa-check:before {\n  content: \"\\f00c\";\n}\n.fa-remove:before,\n.fa-close:before,\n.fa-times:before {\n  content: \"\\f00d\";\n}\n.fa-search-plus:before {\n  content: \"\\f00e\";\n}\n.fa-search-minus:before {\n  content: \"\\f010\";\n}\n.fa-power-off:before {\n  content: \"\\f011\";\n}\n.fa-signal:before {\n  content: \"\\f012\";\n}\n.fa-gear:before,\n.fa-cog:before {\n  content: \"\\f013\";\n}\n.fa-trash-o:before {\n  content: \"\\f014\";\n}\n.fa-home:before {\n  content: \"\\f015\";\n}\n.fa-file-o:before {\n  content: \"\\f016\";\n}\n.fa-clock-o:before {\n  content: \"\\f017\";\n}\n.fa-road:before {\n  content: \"\\f018\";\n}\n.fa-download:before {\n  content: \"\\f019\";\n}\n.fa-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.fa-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.fa-inbox:before {\n  content: \"\\f01c\";\n}\n.fa-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.fa-rotate-right:before,\n.fa-repeat:before {\n  content: \"\\f01e\";\n}\n.fa-refresh:before {\n  content: \"\\f021\";\n}\n.fa-list-alt:before {\n  content: \"\\f022\";\n}\n.fa-lock:before {\n  content: \"\\f023\";\n}\n.fa-flag:before {\n  content: \"\\f024\";\n}\n.fa-headphones:before {\n  content: \"\\f025\";\n}\n.fa-volume-off:before {\n  content: \"\\f026\";\n}\n.fa-volume-down:before {\n  content: \"\\f027\";\n}\n.fa-volume-up:before {\n  content: \"\\f028\";\n}\n.fa-qrcode:before {\n  content: \"\\f029\";\n}\n.fa-barcode:before {\n  content: \"\\f02a\";\n}\n.fa-tag:before {\n  content: \"\\f02b\";\n}\n.fa-tags:before {\n  content: \"\\f02c\";\n}\n.fa-book:before {\n  content: \"\\f02d\";\n}\n.fa-bookmark:before {\n  content: \"\\f02e\";\n}\n.fa-print:before {\n  content: \"\\f02f\";\n}\n.fa-camera:before {\n  content: \"\\f030\";\n}\n.fa-font:before {\n  content: \"\\f031\";\n}\n.fa-bold:before {\n  content: \"\\f032\";\n}\n.fa-italic:before {\n  content: \"\\f033\";\n}\n.fa-text-height:before {\n  content: \"\\f034\";\n}\n.fa-text-width:before {\n  content: \"\\f035\";\n}\n.fa-align-left:before {\n  content: \"\\f036\";\n}\n.fa-align-center:before {\n  content: \"\\f037\";\n}\n.fa-align-right:before {\n  content: \"\\f038\";\n}\n.fa-align-justify:before {\n  content: \"\\f039\";\n}\n.fa-list:before {\n  content: \"\\f03a\";\n}\n.fa-dedent:before,\n.fa-outdent:before {\n  content: \"\\f03b\";\n}\n.fa-indent:before {\n  content: \"\\f03c\";\n}\n.fa-video-camera:before {\n  content: \"\\f03d\";\n}\n.fa-photo:before,\n.fa-image:before,\n.fa-picture-o:before {\n  content: \"\\f03e\";\n}\n.fa-pencil:before {\n  content: \"\\f040\";\n}\n.fa-map-marker:before {\n  content: \"\\f041\";\n}\n.fa-adjust:before {\n  content: \"\\f042\";\n}\n.fa-tint:before {\n  content: \"\\f043\";\n}\n.fa-edit:before,\n.fa-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.fa-share-square-o:before {\n  content: \"\\f045\";\n}\n.fa-check-square-o:before {\n  content: \"\\f046\";\n}\n.fa-arrows:before {\n  content: \"\\f047\";\n}\n.fa-step-backward:before {\n  content: \"\\f048\";\n}\n.fa-fast-backward:before {\n  content: \"\\f049\";\n}\n.fa-backward:before {\n  content: \"\\f04a\";\n}\n.fa-play:before {\n  content: \"\\f04b\";\n}\n.fa-pause:before {\n  content: \"\\f04c\";\n}\n.fa-stop:before {\n  content: \"\\f04d\";\n}\n.fa-forward:before {\n  content: \"\\f04e\";\n}\n.fa-fast-forward:before {\n  content: \"\\f050\";\n}\n.fa-step-forward:before {\n  content: \"\\f051\";\n}\n.fa-eject:before {\n  content: \"\\f052\";\n}\n.fa-chevron-left:before {\n  content: \"\\f053\";\n}\n.fa-chevron-right:before {\n  content: \"\\f054\";\n}\n.fa-plus-circle:before {\n  content: \"\\f055\";\n}\n.fa-minus-circle:before {\n  content: \"\\f056\";\n}\n.fa-times-circle:before {\n  content: \"\\f057\";\n}\n.fa-check-circle:before {\n  content: \"\\f058\";\n}\n.fa-question-circle:before {\n  content: \"\\f059\";\n}\n.fa-info-circle:before {\n  content: \"\\f05a\";\n}\n.fa-crosshairs:before {\n  content: \"\\f05b\";\n}\n.fa-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.fa-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.fa-ban:before {\n  content: \"\\f05e\";\n}\n.fa-arrow-left:before {\n  content: \"\\f060\";\n}\n.fa-arrow-right:before {\n  content: \"\\f061\";\n}\n.fa-arrow-up:before {\n  content: \"\\f062\";\n}\n.fa-arrow-down:before {\n  content: \"\\f063\";\n}\n.fa-mail-forward:before,\n.fa-share:before {\n  content: \"\\f064\";\n}\n.fa-expand:before {\n  content: \"\\f065\";\n}\n.fa-compress:before {\n  content: \"\\f066\";\n}\n.fa-plus:before {\n  content: \"\\f067\";\n}\n.fa-minus:before {\n  content: \"\\f068\";\n}\n.fa-asterisk:before {\n  content: \"\\f069\";\n}\n.fa-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.fa-gift:before {\n  content: \"\\f06b\";\n}\n.fa-leaf:before {\n  content: \"\\f06c\";\n}\n.fa-fire:before {\n  content: \"\\f06d\";\n}\n.fa-eye:before {\n  content: \"\\f06e\";\n}\n.fa-eye-slash:before {\n  content: \"\\f070\";\n}\n.fa-warning:before,\n.fa-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.fa-plane:before {\n  content: \"\\f072\";\n}\n.fa-calendar:before {\n  content: \"\\f073\";\n}\n.fa-random:before {\n  content: \"\\f074\";\n}\n.fa-comment:before {\n  content: \"\\f075\";\n}\n.fa-magnet:before {\n  content: \"\\f076\";\n}\n.fa-chevron-up:before {\n  content: \"\\f077\";\n}\n.fa-chevron-down:before {\n  content: \"\\f078\";\n}\n.fa-retweet:before {\n  content: \"\\f079\";\n}\n.fa-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.fa-folder:before {\n  content: \"\\f07b\";\n}\n.fa-folder-open:before {\n  content: \"\\f07c\";\n}\n.fa-arrows-v:before {\n  content: \"\\f07d\";\n}\n.fa-arrows-h:before {\n  content: \"\\f07e\";\n}\n.fa-bar-chart-o:before,\n.fa-bar-chart:before {\n  content: \"\\f080\";\n}\n.fa-twitter-square:before {\n  content: \"\\f081\";\n}\n.fa-facebook-square:before {\n  content: \"\\f082\";\n}\n.fa-camera-retro:before {\n  content: \"\\f083\";\n}\n.fa-key:before {\n  content: \"\\f084\";\n}\n.fa-gears:before,\n.fa-cogs:before {\n  content: \"\\f085\";\n}\n.fa-comments:before {\n  content: \"\\f086\";\n}\n.fa-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.fa-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.fa-star-half:before {\n  content: \"\\f089\";\n}\n.fa-heart-o:before {\n  content: \"\\f08a\";\n}\n.fa-sign-out:before {\n  content: \"\\f08b\";\n}\n.fa-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.fa-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.fa-external-link:before {\n  content: \"\\f08e\";\n}\n.fa-sign-in:before {\n  content: \"\\f090\";\n}\n.fa-trophy:before {\n  content: \"\\f091\";\n}\n.fa-github-square:before {\n  content: \"\\f092\";\n}\n.fa-upload:before {\n  content: \"\\f093\";\n}\n.fa-lemon-o:before {\n  content: \"\\f094\";\n}\n.fa-phone:before {\n  content: \"\\f095\";\n}\n.fa-square-o:before {\n  content: \"\\f096\";\n}\n.fa-bookmark-o:before {\n  content: \"\\f097\";\n}\n.fa-phone-square:before {\n  content: \"\\f098\";\n}\n.fa-twitter:before {\n  content: \"\\f099\";\n}\n.fa-facebook-f:before,\n.fa-facebook:before {\n  content: \"\\f09a\";\n}\n.fa-github:before {\n  content: \"\\f09b\";\n}\n.fa-unlock:before {\n  content: \"\\f09c\";\n}\n.fa-credit-card:before {\n  content: \"\\f09d\";\n}\n.fa-feed:before,\n.fa-rss:before {\n  content: \"\\f09e\";\n}\n.fa-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.fa-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.fa-bell:before {\n  content: \"\\f0f3\";\n}\n.fa-certificate:before {\n  content: \"\\f0a3\";\n}\n.fa-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.fa-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.fa-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.fa-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.fa-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.fa-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.fa-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.fa-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.fa-globe:before {\n  content: \"\\f0ac\";\n}\n.fa-wrench:before {\n  content: \"\\f0ad\";\n}\n.fa-tasks:before {\n  content: \"\\f0ae\";\n}\n.fa-filter:before {\n  content: \"\\f0b0\";\n}\n.fa-briefcase:before {\n  content: \"\\f0b1\";\n}\n.fa-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.fa-group:before,\n.fa-users:before {\n  content: \"\\f0c0\";\n}\n.fa-chain:before,\n.fa-link:before {\n  content: \"\\f0c1\";\n}\n.fa-cloud:before {\n  content: \"\\f0c2\";\n}\n.fa-flask:before {\n  content: \"\\f0c3\";\n}\n.fa-cut:before,\n.fa-scissors:before {\n  content: \"\\f0c4\";\n}\n.fa-copy:before,\n.fa-files-o:before {\n  content: \"\\f0c5\";\n}\n.fa-paperclip:before {\n  content: \"\\f0c6\";\n}\n.fa-save:before,\n.fa-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.fa-square:before {\n  content: \"\\f0c8\";\n}\n.fa-navicon:before,\n.fa-reorder:before,\n.fa-bars:before {\n  content: \"\\f0c9\";\n}\n.fa-list-ul:before {\n  content: \"\\f0ca\";\n}\n.fa-list-ol:before {\n  content: \"\\f0cb\";\n}\n.fa-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.fa-underline:before {\n  content: \"\\f0cd\";\n}\n.fa-table:before {\n  content: \"\\f0ce\";\n}\n.fa-magic:before {\n  content: \"\\f0d0\";\n}\n.fa-truck:before {\n  content: \"\\f0d1\";\n}\n.fa-pinterest:before {\n  content: \"\\f0d2\";\n}\n.fa-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.fa-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.fa-google-plus:before {\n  content: \"\\f0d5\";\n}\n.fa-money:before {\n  content: \"\\f0d6\";\n}\n.fa-caret-down:before {\n  content: \"\\f0d7\";\n}\n.fa-caret-up:before {\n  content: \"\\f0d8\";\n}\n.fa-caret-left:before {\n  content: \"\\f0d9\";\n}\n.fa-caret-right:before {\n  content: \"\\f0da\";\n}\n.fa-columns:before {\n  content: \"\\f0db\";\n}\n.fa-unsorted:before,\n.fa-sort:before {\n  content: \"\\f0dc\";\n}\n.fa-sort-down:before,\n.fa-sort-desc:before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up:before,\n.fa-sort-asc:before {\n  content: \"\\f0de\";\n}\n.fa-envelope:before {\n  content: \"\\f0e0\";\n}\n.fa-linkedin:before {\n  content: \"\\f0e1\";\n}\n.fa-rotate-left:before,\n.fa-undo:before {\n  content: \"\\f0e2\";\n}\n.fa-legal:before,\n.fa-gavel:before {\n  content: \"\\f0e3\";\n}\n.fa-dashboard:before,\n.fa-tachometer:before {\n  content: \"\\f0e4\";\n}\n.fa-comment-o:before {\n  content: \"\\f0e5\";\n}\n.fa-comments-o:before {\n  content: \"\\f0e6\";\n}\n.fa-flash:before,\n.fa-bolt:before {\n  content: \"\\f0e7\";\n}\n.fa-sitemap:before {\n  content: \"\\f0e8\";\n}\n.fa-umbrella:before {\n  content: \"\\f0e9\";\n}\n.fa-paste:before,\n.fa-clipboard:before {\n  content: \"\\f0ea\";\n}\n.fa-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.fa-exchange:before {\n  content: \"\\f0ec\";\n}\n.fa-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.fa-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.fa-user-md:before {\n  content: \"\\f0f0\";\n}\n.fa-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.fa-suitcase:before {\n  content: \"\\f0f2\";\n}\n.fa-bell-o:before {\n  content: \"\\f0a2\";\n}\n.fa-coffee:before {\n  content: \"\\f0f4\";\n}\n.fa-cutlery:before {\n  content: \"\\f0f5\";\n}\n.fa-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.fa-building-o:before {\n  content: \"\\f0f7\";\n}\n.fa-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.fa-ambulance:before {\n  content: \"\\f0f9\";\n}\n.fa-medkit:before {\n  content: \"\\f0fa\";\n}\n.fa-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.fa-beer:before {\n  content: \"\\f0fc\";\n}\n.fa-h-square:before {\n  content: \"\\f0fd\";\n}\n.fa-plus-square:before {\n  content: \"\\f0fe\";\n}\n.fa-angle-double-left:before {\n  content: \"\\f100\";\n}\n.fa-angle-double-right:before {\n  content: \"\\f101\";\n}\n.fa-angle-double-up:before {\n  content: \"\\f102\";\n}\n.fa-angle-double-down:before {\n  content: \"\\f103\";\n}\n.fa-angle-left:before {\n  content: \"\\f104\";\n}\n.fa-angle-right:before {\n  content: \"\\f105\";\n}\n.fa-angle-up:before {\n  content: \"\\f106\";\n}\n.fa-angle-down:before {\n  content: \"\\f107\";\n}\n.fa-desktop:before {\n  content: \"\\f108\";\n}\n.fa-laptop:before {\n  content: \"\\f109\";\n}\n.fa-tablet:before {\n  content: \"\\f10a\";\n}\n.fa-mobile-phone:before,\n.fa-mobile:before {\n  content: \"\\f10b\";\n}\n.fa-circle-o:before {\n  content: \"\\f10c\";\n}\n.fa-quote-left:before {\n  content: \"\\f10d\";\n}\n.fa-quote-right:before {\n  content: \"\\f10e\";\n}\n.fa-spinner:before {\n  content: \"\\f110\";\n}\n.fa-circle:before {\n  content: \"\\f111\";\n}\n.fa-mail-reply:before,\n.fa-reply:before {\n  content: \"\\f112\";\n}\n.fa-github-alt:before {\n  content: \"\\f113\";\n}\n.fa-folder-o:before {\n  content: \"\\f114\";\n}\n.fa-folder-open-o:before {\n  content: \"\\f115\";\n}\n.fa-smile-o:before {\n  content: \"\\f118\";\n}\n.fa-frown-o:before {\n  content: \"\\f119\";\n}\n.fa-meh-o:before {\n  content: \"\\f11a\";\n}\n.fa-gamepad:before {\n  content: \"\\f11b\";\n}\n.fa-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.fa-flag-o:before {\n  content: \"\\f11d\";\n}\n.fa-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.fa-terminal:before {\n  content: \"\\f120\";\n}\n.fa-code:before {\n  content: \"\\f121\";\n}\n.fa-mail-reply-all:before,\n.fa-reply-all:before {\n  content: \"\\f122\";\n}\n.fa-star-half-empty:before,\n.fa-star-half-full:before,\n.fa-star-half-o:before {\n  content: \"\\f123\";\n}\n.fa-location-arrow:before {\n  content: \"\\f124\";\n}\n.fa-crop:before {\n  content: \"\\f125\";\n}\n.fa-code-fork:before {\n  content: \"\\f126\";\n}\n.fa-unlink:before,\n.fa-chain-broken:before {\n  content: \"\\f127\";\n}\n.fa-question:before {\n  content: \"\\f128\";\n}\n.fa-info:before {\n  content: \"\\f129\";\n}\n.fa-exclamation:before {\n  content: \"\\f12a\";\n}\n.fa-superscript:before {\n  content: \"\\f12b\";\n}\n.fa-subscript:before {\n  content: \"\\f12c\";\n}\n.fa-eraser:before {\n  content: \"\\f12d\";\n}\n.fa-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.fa-microphone:before {\n  content: \"\\f130\";\n}\n.fa-microphone-slash:before {\n  content: \"\\f131\";\n}\n.fa-shield:before {\n  content: \"\\f132\";\n}\n.fa-calendar-o:before {\n  content: \"\\f133\";\n}\n.fa-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.fa-rocket:before {\n  content: \"\\f135\";\n}\n.fa-maxcdn:before {\n  content: \"\\f136\";\n}\n.fa-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.fa-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.fa-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.fa-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.fa-html5:before {\n  content: \"\\f13b\";\n}\n.fa-css3:before {\n  content: \"\\f13c\";\n}\n.fa-anchor:before {\n  content: \"\\f13d\";\n}\n.fa-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.fa-bullseye:before {\n  content: \"\\f140\";\n}\n.fa-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.fa-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.fa-rss-square:before {\n  content: \"\\f143\";\n}\n.fa-play-circle:before {\n  content: \"\\f144\";\n}\n.fa-ticket:before {\n  content: \"\\f145\";\n}\n.fa-minus-square:before {\n  content: \"\\f146\";\n}\n.fa-minus-square-o:before {\n  content: \"\\f147\";\n}\n.fa-level-up:before {\n  content: \"\\f148\";\n}\n.fa-level-down:before {\n  content: \"\\f149\";\n}\n.fa-check-square:before {\n  content: \"\\f14a\";\n}\n.fa-pencil-square:before {\n  content: \"\\f14b\";\n}\n.fa-external-link-square:before {\n  content: \"\\f14c\";\n}\n.fa-share-square:before {\n  content: \"\\f14d\";\n}\n.fa-compass:before {\n  content: \"\\f14e\";\n}\n.fa-toggle-down:before,\n.fa-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.fa-toggle-up:before,\n.fa-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.fa-toggle-right:before,\n.fa-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.fa-euro:before,\n.fa-eur:before {\n  content: \"\\f153\";\n}\n.fa-gbp:before {\n  content: \"\\f154\";\n}\n.fa-dollar:before,\n.fa-usd:before {\n  content: \"\\f155\";\n}\n.fa-rupee:before,\n.fa-inr:before {\n  content: \"\\f156\";\n}\n.fa-cny:before,\n.fa-rmb:before,\n.fa-yen:before,\n.fa-jpy:before {\n  content: \"\\f157\";\n}\n.fa-ruble:before,\n.fa-rouble:before,\n.fa-rub:before {\n  content: \"\\f158\";\n}\n.fa-won:before,\n.fa-krw:before {\n  content: \"\\f159\";\n}\n.fa-bitcoin:before,\n.fa-btc:before {\n  content: \"\\f15a\";\n}\n.fa-file:before {\n  content: \"\\f15b\";\n}\n.fa-file-text:before {\n  content: \"\\f15c\";\n}\n.fa-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.fa-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.fa-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.fa-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.fa-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.fa-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.fa-thumbs-up:before {\n  content: \"\\f164\";\n}\n.fa-thumbs-down:before {\n  content: \"\\f165\";\n}\n.fa-youtube-square:before {\n  content: \"\\f166\";\n}\n.fa-youtube:before {\n  content: \"\\f167\";\n}\n.fa-xing:before {\n  content: \"\\f168\";\n}\n.fa-xing-square:before {\n  content: \"\\f169\";\n}\n.fa-youtube-play:before {\n  content: \"\\f16a\";\n}\n.fa-dropbox:before {\n  content: \"\\f16b\";\n}\n.fa-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.fa-instagram:before {\n  content: \"\\f16d\";\n}\n.fa-flickr:before {\n  content: \"\\f16e\";\n}\n.fa-adn:before {\n  content: \"\\f170\";\n}\n.fa-bitbucket:before {\n  content: \"\\f171\";\n}\n.fa-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.fa-tumblr:before {\n  content: \"\\f173\";\n}\n.fa-tumblr-square:before {\n  content: \"\\f174\";\n}\n.fa-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.fa-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.fa-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.fa-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.fa-apple:before {\n  content: \"\\f179\";\n}\n.fa-windows:before {\n  content: \"\\f17a\";\n}\n.fa-android:before {\n  content: \"\\f17b\";\n}\n.fa-linux:before {\n  content: \"\\f17c\";\n}\n.fa-dribbble:before {\n  content: \"\\f17d\";\n}\n.fa-skype:before {\n  content: \"\\f17e\";\n}\n.fa-foursquare:before {\n  content: \"\\f180\";\n}\n.fa-trello:before {\n  content: \"\\f181\";\n}\n.fa-female:before {\n  content: \"\\f182\";\n}\n.fa-male:before {\n  content: \"\\f183\";\n}\n.fa-gittip:before,\n.fa-gratipay:before {\n  content: \"\\f184\";\n}\n.fa-sun-o:before {\n  content: \"\\f185\";\n}\n.fa-moon-o:before {\n  content: \"\\f186\";\n}\n.fa-archive:before {\n  content: \"\\f187\";\n}\n.fa-bug:before {\n  content: \"\\f188\";\n}\n.fa-vk:before {\n  content: \"\\f189\";\n}\n.fa-weibo:before {\n  content: \"\\f18a\";\n}\n.fa-renren:before {\n  content: \"\\f18b\";\n}\n.fa-pagelines:before {\n  content: \"\\f18c\";\n}\n.fa-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.fa-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.fa-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.fa-toggle-left:before,\n.fa-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.fa-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.fa-wheelchair:before {\n  content: \"\\f193\";\n}\n.fa-vimeo-square:before {\n  content: \"\\f194\";\n}\n.fa-turkish-lira:before,\n.fa-try:before {\n  content: \"\\f195\";\n}\n.fa-plus-square-o:before {\n  content: \"\\f196\";\n}\n.fa-space-shuttle:before {\n  content: \"\\f197\";\n}\n.fa-slack:before {\n  content: \"\\f198\";\n}\n.fa-envelope-square:before {\n  content: \"\\f199\";\n}\n.fa-wordpress:before {\n  content: \"\\f19a\";\n}\n.fa-openid:before {\n  content: \"\\f19b\";\n}\n.fa-institution:before,\n.fa-bank:before,\n.fa-university:before {\n  content: \"\\f19c\";\n}\n.fa-mortar-board:before,\n.fa-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.fa-yahoo:before {\n  content: \"\\f19e\";\n}\n.fa-google:before {\n  content: \"\\f1a0\";\n}\n.fa-reddit:before {\n  content: \"\\f1a1\";\n}\n.fa-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.fa-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.fa-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.fa-delicious:before {\n  content: \"\\f1a5\";\n}\n.fa-digg:before {\n  content: \"\\f1a6\";\n}\n.fa-pied-piper-pp:before {\n  content: \"\\f1a7\";\n}\n.fa-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.fa-drupal:before {\n  content: \"\\f1a9\";\n}\n.fa-joomla:before {\n  content: \"\\f1aa\";\n}\n.fa-language:before {\n  content: \"\\f1ab\";\n}\n.fa-fax:before {\n  content: \"\\f1ac\";\n}\n.fa-building:before {\n  content: \"\\f1ad\";\n}\n.fa-child:before {\n  content: \"\\f1ae\";\n}\n.fa-paw:before {\n  content: \"\\f1b0\";\n}\n.fa-spoon:before {\n  content: \"\\f1b1\";\n}\n.fa-cube:before {\n  content: \"\\f1b2\";\n}\n.fa-cubes:before {\n  content: \"\\f1b3\";\n}\n.fa-behance:before {\n  content: \"\\f1b4\";\n}\n.fa-behance-square:before {\n  content: \"\\f1b5\";\n}\n.fa-steam:before {\n  content: \"\\f1b6\";\n}\n.fa-steam-square:before {\n  content: \"\\f1b7\";\n}\n.fa-recycle:before {\n  content: \"\\f1b8\";\n}\n.fa-automobile:before,\n.fa-car:before {\n  content: \"\\f1b9\";\n}\n.fa-cab:before,\n.fa-taxi:before {\n  content: \"\\f1ba\";\n}\n.fa-tree:before {\n  content: \"\\f1bb\";\n}\n.fa-spotify:before {\n  content: \"\\f1bc\";\n}\n.fa-deviantart:before {\n  content: \"\\f1bd\";\n}\n.fa-soundcloud:before {\n  content: \"\\f1be\";\n}\n.fa-database:before {\n  content: \"\\f1c0\";\n}\n.fa-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.fa-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.fa-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.fa-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.fa-file-photo-o:before,\n.fa-file-picture-o:before,\n.fa-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.fa-file-zip-o:before,\n.fa-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.fa-file-sound-o:before,\n.fa-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.fa-file-movie-o:before,\n.fa-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.fa-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.fa-vine:before {\n  content: \"\\f1ca\";\n}\n.fa-codepen:before {\n  content: \"\\f1cb\";\n}\n.fa-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.fa-life-bouy:before,\n.fa-life-buoy:before,\n.fa-life-saver:before,\n.fa-support:before,\n.fa-life-ring:before {\n  content: \"\\f1cd\";\n}\n.fa-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.fa-ra:before,\n.fa-resistance:before,\n.fa-rebel:before {\n  content: \"\\f1d0\";\n}\n.fa-ge:before,\n.fa-empire:before {\n  content: \"\\f1d1\";\n}\n.fa-git-square:before {\n  content: \"\\f1d2\";\n}\n.fa-git:before {\n  content: \"\\f1d3\";\n}\n.fa-y-combinator-square:before,\n.fa-yc-square:before,\n.fa-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.fa-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.fa-qq:before {\n  content: \"\\f1d6\";\n}\n.fa-wechat:before,\n.fa-weixin:before {\n  content: \"\\f1d7\";\n}\n.fa-send:before,\n.fa-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.fa-send-o:before,\n.fa-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.fa-history:before {\n  content: \"\\f1da\";\n}\n.fa-circle-thin:before {\n  content: \"\\f1db\";\n}\n.fa-header:before {\n  content: \"\\f1dc\";\n}\n.fa-paragraph:before {\n  content: \"\\f1dd\";\n}\n.fa-sliders:before {\n  content: \"\\f1de\";\n}\n.fa-share-alt:before {\n  content: \"\\f1e0\";\n}\n.fa-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.fa-bomb:before {\n  content: \"\\f1e2\";\n}\n.fa-soccer-ball-o:before,\n.fa-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.fa-tty:before {\n  content: \"\\f1e4\";\n}\n.fa-binoculars:before {\n  content: \"\\f1e5\";\n}\n.fa-plug:before {\n  content: \"\\f1e6\";\n}\n.fa-slideshare:before {\n  content: \"\\f1e7\";\n}\n.fa-twitch:before {\n  content: \"\\f1e8\";\n}\n.fa-yelp:before {\n  content: \"\\f1e9\";\n}\n.fa-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.fa-wifi:before {\n  content: \"\\f1eb\";\n}\n.fa-calculator:before {\n  content: \"\\f1ec\";\n}\n.fa-paypal:before {\n  content: \"\\f1ed\";\n}\n.fa-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.fa-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.fa-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.fa-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.fa-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.fa-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.fa-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.fa-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.fa-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.fa-trash:before {\n  content: \"\\f1f8\";\n}\n.fa-copyright:before {\n  content: \"\\f1f9\";\n}\n.fa-at:before {\n  content: \"\\f1fa\";\n}\n.fa-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.fa-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.fa-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.fa-area-chart:before {\n  content: \"\\f1fe\";\n}\n.fa-pie-chart:before {\n  content: \"\\f200\";\n}\n.fa-line-chart:before {\n  content: \"\\f201\";\n}\n.fa-lastfm:before {\n  content: \"\\f202\";\n}\n.fa-lastfm-square:before {\n  content: \"\\f203\";\n}\n.fa-toggle-off:before {\n  content: \"\\f204\";\n}\n.fa-toggle-on:before {\n  content: \"\\f205\";\n}\n.fa-bicycle:before {\n  content: \"\\f206\";\n}\n.fa-bus:before {\n  content: \"\\f207\";\n}\n.fa-ioxhost:before {\n  content: \"\\f208\";\n}\n.fa-angellist:before {\n  content: \"\\f209\";\n}\n.fa-cc:before {\n  content: \"\\f20a\";\n}\n.fa-shekel:before,\n.fa-sheqel:before,\n.fa-ils:before {\n  content: \"\\f20b\";\n}\n.fa-meanpath:before {\n  content: \"\\f20c\";\n}\n.fa-buysellads:before {\n  content: \"\\f20d\";\n}\n.fa-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.fa-dashcube:before {\n  content: \"\\f210\";\n}\n.fa-forumbee:before {\n  content: \"\\f211\";\n}\n.fa-leanpub:before {\n  content: \"\\f212\";\n}\n.fa-sellsy:before {\n  content: \"\\f213\";\n}\n.fa-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.fa-simplybuilt:before {\n  content: \"\\f215\";\n}\n.fa-skyatlas:before {\n  content: \"\\f216\";\n}\n.fa-cart-plus:before {\n  content: \"\\f217\";\n}\n.fa-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.fa-diamond:before {\n  content: \"\\f219\";\n}\n.fa-ship:before {\n  content: \"\\f21a\";\n}\n.fa-user-secret:before {\n  content: \"\\f21b\";\n}\n.fa-motorcycle:before {\n  content: \"\\f21c\";\n}\n.fa-street-view:before {\n  content: \"\\f21d\";\n}\n.fa-heartbeat:before {\n  content: \"\\f21e\";\n}\n.fa-venus:before {\n  content: \"\\f221\";\n}\n.fa-mars:before {\n  content: \"\\f222\";\n}\n.fa-mercury:before {\n  content: \"\\f223\";\n}\n.fa-intersex:before,\n.fa-transgender:before {\n  content: \"\\f224\";\n}\n.fa-transgender-alt:before {\n  content: \"\\f225\";\n}\n.fa-venus-double:before {\n  content: \"\\f226\";\n}\n.fa-mars-double:before {\n  content: \"\\f227\";\n}\n.fa-venus-mars:before {\n  content: \"\\f228\";\n}\n.fa-mars-stroke:before {\n  content: \"\\f229\";\n}\n.fa-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.fa-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.fa-neuter:before {\n  content: \"\\f22c\";\n}\n.fa-genderless:before {\n  content: \"\\f22d\";\n}\n.fa-facebook-official:before {\n  content: \"\\f230\";\n}\n.fa-pinterest-p:before {\n  content: \"\\f231\";\n}\n.fa-whatsapp:before {\n  content: \"\\f232\";\n}\n.fa-server:before {\n  content: \"\\f233\";\n}\n.fa-user-plus:before {\n  content: \"\\f234\";\n}\n.fa-user-times:before {\n  content: \"\\f235\";\n}\n.fa-hotel:before,\n.fa-bed:before {\n  content: \"\\f236\";\n}\n.fa-viacoin:before {\n  content: \"\\f237\";\n}\n.fa-train:before {\n  content: \"\\f238\";\n}\n.fa-subway:before {\n  content: \"\\f239\";\n}\n.fa-medium:before {\n  content: \"\\f23a\";\n}\n.fa-yc:before,\n.fa-y-combinator:before {\n  content: \"\\f23b\";\n}\n.fa-optin-monster:before {\n  content: \"\\f23c\";\n}\n.fa-opencart:before {\n  content: \"\\f23d\";\n}\n.fa-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.fa-battery-4:before,\n.fa-battery:before,\n.fa-battery-full:before {\n  content: \"\\f240\";\n}\n.fa-battery-3:before,\n.fa-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.fa-battery-2:before,\n.fa-battery-half:before {\n  content: \"\\f242\";\n}\n.fa-battery-1:before,\n.fa-battery-quarter:before {\n  content: \"\\f243\";\n}\n.fa-battery-0:before,\n.fa-battery-empty:before {\n  content: \"\\f244\";\n}\n.fa-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.fa-i-cursor:before {\n  content: \"\\f246\";\n}\n.fa-object-group:before {\n  content: \"\\f247\";\n}\n.fa-object-ungroup:before {\n  content: \"\\f248\";\n}\n.fa-sticky-note:before {\n  content: \"\\f249\";\n}\n.fa-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.fa-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.fa-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.fa-clone:before {\n  content: \"\\f24d\";\n}\n.fa-balance-scale:before {\n  content: \"\\f24e\";\n}\n.fa-hourglass-o:before {\n  content: \"\\f250\";\n}\n.fa-hourglass-1:before,\n.fa-hourglass-start:before {\n  content: \"\\f251\";\n}\n.fa-hourglass-2:before,\n.fa-hourglass-half:before {\n  content: \"\\f252\";\n}\n.fa-hourglass-3:before,\n.fa-hourglass-end:before {\n  content: \"\\f253\";\n}\n.fa-hourglass:before {\n  content: \"\\f254\";\n}\n.fa-hand-grab-o:before,\n.fa-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.fa-hand-stop-o:before,\n.fa-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.fa-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.fa-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.fa-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.fa-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.fa-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.fa-trademark:before {\n  content: \"\\f25c\";\n}\n.fa-registered:before {\n  content: \"\\f25d\";\n}\n.fa-creative-commons:before {\n  content: \"\\f25e\";\n}\n.fa-gg:before {\n  content: \"\\f260\";\n}\n.fa-gg-circle:before {\n  content: \"\\f261\";\n}\n.fa-tripadvisor:before {\n  content: \"\\f262\";\n}\n.fa-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.fa-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.fa-get-pocket:before {\n  content: \"\\f265\";\n}\n.fa-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.fa-safari:before {\n  content: \"\\f267\";\n}\n.fa-chrome:before {\n  content: \"\\f268\";\n}\n.fa-firefox:before {\n  content: \"\\f269\";\n}\n.fa-opera:before {\n  content: \"\\f26a\";\n}\n.fa-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.fa-tv:before,\n.fa-television:before {\n  content: \"\\f26c\";\n}\n.fa-contao:before {\n  content: \"\\f26d\";\n}\n.fa-500px:before {\n  content: \"\\f26e\";\n}\n.fa-amazon:before {\n  content: \"\\f270\";\n}\n.fa-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.fa-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.fa-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.fa-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.fa-industry:before {\n  content: \"\\f275\";\n}\n.fa-map-pin:before {\n  content: \"\\f276\";\n}\n.fa-map-signs:before {\n  content: \"\\f277\";\n}\n.fa-map-o:before {\n  content: \"\\f278\";\n}\n.fa-map:before {\n  content: \"\\f279\";\n}\n.fa-commenting:before {\n  content: \"\\f27a\";\n}\n.fa-commenting-o:before {\n  content: \"\\f27b\";\n}\n.fa-houzz:before {\n  content: \"\\f27c\";\n}\n.fa-vimeo:before {\n  content: \"\\f27d\";\n}\n.fa-black-tie:before {\n  content: \"\\f27e\";\n}\n.fa-fonticons:before {\n  content: \"\\f280\";\n}\n.fa-reddit-alien:before {\n  content: \"\\f281\";\n}\n.fa-edge:before {\n  content: \"\\f282\";\n}\n.fa-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.fa-codiepie:before {\n  content: \"\\f284\";\n}\n.fa-modx:before {\n  content: \"\\f285\";\n}\n.fa-fort-awesome:before {\n  content: \"\\f286\";\n}\n.fa-usb:before {\n  content: \"\\f287\";\n}\n.fa-product-hunt:before {\n  content: \"\\f288\";\n}\n.fa-mixcloud:before {\n  content: \"\\f289\";\n}\n.fa-scribd:before {\n  content: \"\\f28a\";\n}\n.fa-pause-circle:before {\n  content: \"\\f28b\";\n}\n.fa-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.fa-stop-circle:before {\n  content: \"\\f28d\";\n}\n.fa-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.fa-shopping-bag:before {\n  content: \"\\f290\";\n}\n.fa-shopping-basket:before {\n  content: \"\\f291\";\n}\n.fa-hashtag:before {\n  content: \"\\f292\";\n}\n.fa-bluetooth:before {\n  content: \"\\f293\";\n}\n.fa-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.fa-percent:before {\n  content: \"\\f295\";\n}\n.fa-gitlab:before {\n  content: \"\\f296\";\n}\n.fa-wpbeginner:before {\n  content: \"\\f297\";\n}\n.fa-wpforms:before {\n  content: \"\\f298\";\n}\n.fa-envira:before {\n  content: \"\\f299\";\n}\n.fa-universal-access:before {\n  content: \"\\f29a\";\n}\n.fa-wheelchair-alt:before {\n  content: \"\\f29b\";\n}\n.fa-question-circle-o:before {\n  content: \"\\f29c\";\n}\n.fa-blind:before {\n  content: \"\\f29d\";\n}\n.fa-audio-description:before {\n  content: \"\\f29e\";\n}\n.fa-volume-control-phone:before {\n  content: \"\\f2a0\";\n}\n.fa-braille:before {\n  content: \"\\f2a1\";\n}\n.fa-assistive-listening-systems:before {\n  content: \"\\f2a2\";\n}\n.fa-asl-interpreting:before,\n.fa-american-sign-language-interpreting:before {\n  content: \"\\f2a3\";\n}\n.fa-deafness:before,\n.fa-hard-of-hearing:before,\n.fa-deaf:before {\n  content: \"\\f2a4\";\n}\n.fa-glide:before {\n  content: \"\\f2a5\";\n}\n.fa-glide-g:before {\n  content: \"\\f2a6\";\n}\n.fa-signing:before,\n.fa-sign-language:before {\n  content: \"\\f2a7\";\n}\n.fa-low-vision:before {\n  content: \"\\f2a8\";\n}\n.fa-viadeo:before {\n  content: \"\\f2a9\";\n}\n.fa-viadeo-square:before {\n  content: \"\\f2aa\";\n}\n.fa-snapchat:before {\n  content: \"\\f2ab\";\n}\n.fa-snapchat-ghost:before {\n  content: \"\\f2ac\";\n}\n.fa-snapchat-square:before {\n  content: \"\\f2ad\";\n}\n.fa-pied-piper:before {\n  content: \"\\f2ae\";\n}\n.fa-first-order:before {\n  content: \"\\f2b0\";\n}\n.fa-yoast:before {\n  content: \"\\f2b1\";\n}\n.fa-themeisle:before {\n  content: \"\\f2b2\";\n}\n.fa-google-plus-circle:before,\n.fa-google-plus-official:before {\n  content: \"\\f2b3\";\n}\n.fa-fa:before,\n.fa-font-awesome:before {\n  content: \"\\f2b4\";\n}\n.fa-handshake-o:before {\n  content: \"\\f2b5\";\n}\n.fa-envelope-open:before {\n  content: \"\\f2b6\";\n}\n.fa-envelope-open-o:before {\n  content: \"\\f2b7\";\n}\n.fa-linode:before {\n  content: \"\\f2b8\";\n}\n.fa-address-book:before {\n  content: \"\\f2b9\";\n}\n.fa-address-book-o:before {\n  content: \"\\f2ba\";\n}\n.fa-vcard:before,\n.fa-address-card:before {\n  content: \"\\f2bb\";\n}\n.fa-vcard-o:before,\n.fa-address-card-o:before {\n  content: \"\\f2bc\";\n}\n.fa-user-circle:before {\n  content: \"\\f2bd\";\n}\n.fa-user-circle-o:before {\n  content: \"\\f2be\";\n}\n.fa-user-o:before {\n  content: \"\\f2c0\";\n}\n.fa-id-badge:before {\n  content: \"\\f2c1\";\n}\n.fa-drivers-license:before,\n.fa-id-card:before {\n  content: \"\\f2c2\";\n}\n.fa-drivers-license-o:before,\n.fa-id-card-o:before {\n  content: \"\\f2c3\";\n}\n.fa-quora:before {\n  content: \"\\f2c4\";\n}\n.fa-free-code-camp:before {\n  content: \"\\f2c5\";\n}\n.fa-telegram:before {\n  content: \"\\f2c6\";\n}\n.fa-thermometer-4:before,\n.fa-thermometer:before,\n.fa-thermometer-full:before {\n  content: \"\\f2c7\";\n}\n.fa-thermometer-3:before,\n.fa-thermometer-three-quarters:before {\n  content: \"\\f2c8\";\n}\n.fa-thermometer-2:before,\n.fa-thermometer-half:before {\n  content: \"\\f2c9\";\n}\n.fa-thermometer-1:before,\n.fa-thermometer-quarter:before {\n  content: \"\\f2ca\";\n}\n.fa-thermometer-0:before,\n.fa-thermometer-empty:before {\n  content: \"\\f2cb\";\n}\n.fa-shower:before {\n  content: \"\\f2cc\";\n}\n.fa-bathtub:before,\n.fa-s15:before,\n.fa-bath:before {\n  content: \"\\f2cd\";\n}\n.fa-podcast:before {\n  content: \"\\f2ce\";\n}\n.fa-window-maximize:before {\n  content: \"\\f2d0\";\n}\n.fa-window-minimize:before {\n  content: \"\\f2d1\";\n}\n.fa-window-restore:before {\n  content: \"\\f2d2\";\n}\n.fa-times-rectangle:before,\n.fa-window-close:before {\n  content: \"\\f2d3\";\n}\n.fa-times-rectangle-o:before,\n.fa-window-close-o:before {\n  content: \"\\f2d4\";\n}\n.fa-bandcamp:before {\n  content: \"\\f2d5\";\n}\n.fa-grav:before {\n  content: \"\\f2d6\";\n}\n.fa-etsy:before {\n  content: \"\\f2d7\";\n}\n.fa-imdb:before {\n  content: \"\\f2d8\";\n}\n.fa-ravelry:before {\n  content: \"\\f2d9\";\n}\n.fa-eercast:before {\n  content: \"\\f2da\";\n}\n.fa-microchip:before {\n  content: \"\\f2db\";\n}\n.fa-snowflake-o:before {\n  content: \"\\f2dc\";\n}\n.fa-superpowers:before {\n  content: \"\\f2dd\";\n}\n.fa-wpexplorer:before {\n  content: \"\\f2de\";\n}\n.fa-meetup:before {\n  content: \"\\f2e0\";\n}\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  margin: 0;\n  overflow: visible;\n  clip: auto;\n}\n"
  },
  {
    "path": "index.dev.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>ONI</title>\n    <link rel=\"stylesheet\" href=\"font-awesome/css/font-awesome.min.css\">\n    <style>\n        html, body {\n            width: 100%;\n            height: 100%;\n            padding: 0px;\n            margin: 0px;\n            overflow: hidden;\n        }\n        body {\n            font-family: Consolas, Monaco, 'Courier New', monospace;\n            font-size: 14px;\n        }\n\n        script {\n            display: none;\n        }\n\n        @keyframes spinner-rotate {\n            0% { transform: rotateY(0deg); }\n            100% { transform: rotateY(360deg); }\n        }\n\n        .webpack-loading-image {\n            animation: spinner-rotate 2s linear infinite;\n        }\n    </style>\n  </head>\n  <body>\n    <div id=\"host\"></div>\n    <script src=\"preload.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"Content-Security-Policy\" content=\"default-src *; img-src blob: data: *; script-src 'self' http://localhost:8191; style-src 'self' 'unsafe-inline'; media-src blob: data: mediastream: *;\">\n    <title>ONI</title>\n    <link rel=\"stylesheet\" href=\"font-awesome/css/font-awesome.min.css\">\n    <style>\n        html, body {\n            width: 100%;\n            height: 100%;\n            padding: 0px;\n            margin: 0px;\n            overflow: hidden;\n        }\n        body {\n            font-family: Consolas, Monaco, 'Courier New', monospace;\n            font-size: 14px;\n        }\n\n        script {\n            display: none;\n        }\n\n        @keyframes spinner-rotate {\n            0% { transform: rotateY(0deg); }\n            100% { transform: rotateY(360deg); }\n        }\n\n        .webpack-loading-image {\n            animation: spinner-rotate 2s linear infinite;\n        }\n    </style>\n  </head>\n  <body>\n    <div id=\"host\"></div>\n    <script src=\"preload.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n    bail: true,\n    verbose: false,\n    collectCoverage: true,\n    coverageDirectory: \"<rootDir>/coverage/jest/\",\n    setupFiles: [\"<rootDir>/ui-tests/jestsetup.ts\"],\n    moduleNameMapper: {\n        electron: \"<rootDir>/ui-tests/mocks/electronMock.ts\",\n        PersistentSettings: \"<rootDir>/ui-tests/mocks/PersistentSettings.ts\",\n        Utility: \"<rootDir>/ui-tests/mocks/Utility.ts\",\n        Configuration: \"<rootDir>/ui-tests/mocks/Configuration.ts\",\n        UserConfiguration: \"<rootDir>/ui-tests/mocks/UserConfiguration.ts\",\n        KeyboardLayout: \"<rootDir>/ui-tests/mocks/keyboardLayout.ts\",\n        SharedNeovimInstance: \"<rootDir>/ui-tests/mocks/SharedNeovimInstance.ts\",\n    },\n    snapshotSerializers: [\"enzyme-to-json/serializer\"],\n    transform: {\n        \"^.+\\\\.tsx?$\": \"ts-jest\",\n    },\n    testRegex: \"(/__tests__/.*|(\\\\.|/)(test|spec))\\\\.(jsx?|tsx?)$\",\n    moduleFileExtensions: [\"ts\", \"tsx\", \"js\", \"jsx\", \"json\", \"node\"],\n    modulePathIgnorePatterns: [\"<rootDir>/dist/\"],\n    globals: {\n        \"ts-jest\": {\n            babelConfig: {\n                env: {\n                    test: {\n                        plugins: [\"dynamic-import-node\"],\n                    },\n                },\n            },\n            tsConfigFile: \"./ui-tests/tsconfig.react.json\",\n        },\n    },\n}\n"
  },
  {
    "path": "main/src/Log.ts",
    "content": "/**\n * Log.ts\n *\n * Log helper methods for the main process\n */\n\nconst logs = []\n\nlet _isVerbose = false\n\nconst isVerbose = () =>\n    process.argv.some(arg => arg.includes(\"--verbose\")) || _isVerbose\n\nexport const setVerbose = (verbose: boolean) => {\n    _isVerbose = verbose\n}\n\nexport const info = (msg: string): void => {\n    if (isVerbose()) {\n        console.log(msg) // tslint:disable-line no-console\n    }\n\n    logs.push(msg)\n}\n\nexport const warn = (msg: string): void => {\n    if (isVerbose()) {\n        console.warn(msg) // tslint:disable-line no-console\n    }\n\n    logs.push(msg)\n}\n\nexport const getAllLogs = () => {\n    return logs\n}\n"
  },
  {
    "path": "main/src/ProcessLifecycle.ts",
    "content": "import { app } from \"electron\"\n\nexport const makeSingleInstance = (options, callbackFunction) => {\n    const isSecondInstance = app.makeSingleInstance((args, workingDirectory) => {\n        callbackFunction({\n            args,\n            workingDirectory,\n        })\n    })\n\n    if (isSecondInstance) {\n        app.quit()\n    }\n\n    app.on(\"ready\", () => {\n        callbackFunction(options)\n    })\n}\n"
  },
  {
    "path": "main/src/WindowManager.ts",
    "content": "import { BrowserWindow, Rectangle } from \"electron\"\nimport * as Log from \"./Log\"\n\n// Function to process moving to the next Oni window, given a direction.\nexport function moveToNextOniInstance(windows: BrowserWindow[], direction: string) {\n    const currentFocusedWindows = windows.filter(f => f.isFocused())\n\n    if (currentFocusedWindows.length === 0) {\n        Log.info(\"No window currently focused\")\n        return\n    } else if (windows.length === 1) {\n        Log.info(\"No window to swap to\")\n        return\n    }\n\n    const currentFocusedWindow = currentFocusedWindows[0]\n    const windowsToCheck = windows.filter(\n        window => window !== currentFocusedWindow && !window.isMinimized(),\n    )\n\n    const validWindows = windowsToCheck.filter(window =>\n        windowIsInValidDirection(direction, currentFocusedWindow.getBounds(), window.getBounds()),\n    )\n\n    if (validWindows.length === 0) {\n        return\n    }\n\n    const windowToSwapTo = validWindows.reduce<BrowserWindow>((curr, prev) => {\n        const isCurrentWindowBetter = checkWindowToFindBest(\n            currentFocusedWindow.getBounds(),\n            curr.getBounds(),\n            prev.getBounds(),\n            direction,\n        )\n\n        if (isCurrentWindowBetter) {\n            return curr\n        } else {\n            return prev\n        }\n    }, validWindows[0])\n\n    windows[windows.indexOf(windowToSwapTo)].focus()\n}\n\nexport function windowIsInValidDirection(\n    direction: string,\n    currentPos: Rectangle,\n    testPos: Rectangle,\n) {\n    let valuesIncrease = false\n    let coord = \"x\"\n\n    switch (direction) {\n        case \"left\":\n            valuesIncrease = false\n            break\n        case \"right\":\n            valuesIncrease = true\n            break\n        case \"up\":\n            valuesIncrease = false\n            coord = \"y\"\n            break\n        case \"down\":\n            valuesIncrease = true\n            coord = \"y\"\n            break\n        default:\n            return false\n    }\n\n    // Check if the screen we are testing is in the right direction.\n    // shouldBeBigger is used for moving to the right or down, since the X/Y values increase.\n    // Othewise, we want the value that decreases (i.e. for left or up)\n    if (valuesIncrease) {\n        if (testPos[coord] > currentPos[coord]) {\n            return true\n        }\n    } else {\n        if (testPos[coord] < currentPos[coord]) {\n            return true\n        }\n    }\n\n    return false\n}\n\n// Given a window, check if it is the best window seen so far.\n// This is determined by the difference in X and Y relative to the current window.\nexport function checkWindowToFindBest(\n    currentWindow: Rectangle,\n    testWindow: Rectangle,\n    currentBest: Rectangle,\n    direction: string,\n) {\n    const differenceInX = Math.abs(currentWindow.x - testWindow.x)\n    const differenceInY = Math.abs(currentWindow.y - testWindow.y)\n\n    const bestDiffInX = Math.abs(currentWindow.x - currentBest.x)\n    const bestDiffInY = Math.abs(currentWindow.y - currentBest.y)\n\n    // Use the main axis such that we always move to the closest window in the\n    // direction we are moving.\n    let mainAxisDiff = DistanceComparison.larger\n    let secondAxisDiff = DistanceComparison.larger\n\n    switch (direction) {\n        case \"left\":\n        case \"right\":\n            mainAxisDiff = compareDistances(differenceInX, bestDiffInX)\n            secondAxisDiff = compareDistances(differenceInY, bestDiffInY)\n            break\n        case \"up\":\n        case \"down\":\n            mainAxisDiff = compareDistances(differenceInY, bestDiffInY)\n            secondAxisDiff = compareDistances(differenceInX, bestDiffInX)\n            break\n        default:\n            return false\n    }\n\n    // If an equal distance away, we should check the other axis and\n    // take the one that is closer in that axis.\n    // If they are both the same? Just use the current one.\n    if (mainAxisDiff === DistanceComparison.smaller) {\n        return true\n    } else if (\n        mainAxisDiff === DistanceComparison.equal &&\n        secondAxisDiff === DistanceComparison.smaller\n    ) {\n        return true\n    } else {\n        return false\n    }\n}\n\nexport enum DistanceComparison {\n    smaller,\n    larger,\n    equal,\n}\n\n// Helper function to compare the distances and return how the values\n// compare.\nexport function compareDistances(currentDifference: number, bestDifference: number) {\n    if (currentDifference === bestDifference) {\n        return DistanceComparison.equal\n    } else if (currentDifference < bestDifference) {\n        return DistanceComparison.smaller\n    } else {\n        return DistanceComparison.larger\n    }\n}\n"
  },
  {
    "path": "main/src/installDevTools.ts",
    "content": "/**\r\n * installDevTools.ts\r\n *\r\n * Helper to install the redux & react devtools\r\n */\r\n\r\nimport * as Log from \"./Log\"\r\nexport default async () => {\r\n    try {\r\n        const {\r\n            REACT_DEVELOPER_TOOLS,\r\n            REDUX_DEVTOOLS,\r\n            default: installExtension,\r\n        } = require(\"electron-devtools-installer\")\r\n        try {\r\n            const reduxExt = await installExtension(REDUX_DEVTOOLS)\r\n            Log.info(`Added extension: ${reduxExt}`)\r\n            const reactExt = await installExtension(REACT_DEVELOPER_TOOLS)\r\n            Log.info(`Added extension: ${reactExt}`)\r\n        } catch (e) {\r\n            Log.info(`An error occurred: ${e}`)\r\n        }\r\n    } catch (ex) {\r\n        Log.warn(\r\n            \"Unable to install developer tools. `electron-devtools-installer` may not be available in this environment\",\r\n        )\r\n    }\r\n}\r\n"
  },
  {
    "path": "main/src/main.ts",
    "content": "import * as path from \"path\"\n\nimport { app, BrowserWindow, ipcMain, Menu } from \"electron\"\n\nimport * as PersistentSettings from \"electron-settings\"\n\nimport addDevExtensions from \"./installDevTools\"\nimport * as Log from \"./Log\"\nimport { buildDockMenu, buildMenu } from \"./menu\"\nimport { makeSingleInstance } from \"./ProcessLifecycle\"\nimport { moveToNextOniInstance } from \"./WindowManager\"\n\nglobal[\"getLogs\"] = Log.getAllLogs // tslint:disable-line no-string-literal\n\nconst processArgs = process.argv || []\nconst isAutomation = processArgs.find(f => f.indexOf(\"--test-type=webdriver\") >= 0)\nconst isDevelopment = process.env.NODE_ENV === \"development\" || process.env.ONI_WEBPACK_LOAD === \"1\"\nconst isDebug = process.argv.filter(arg => arg.indexOf(\"--debug\") >= 0).length > 0\n\nif (isAutomation) {\n    Log.setVerbose(true)\n    Log.info(\"Verbose flag set since running automation\")\n}\n\n// const argv = minimist(process.argv.slice(1))\n\ninterface IWindowState {\n    bounds?: {\n        x: number\n        y: number\n        height: number\n        width: number\n    }\n    isMaximized?: boolean\n}\n\nlet windowState: IWindowState = {\n    bounds: {\n        x: null,\n        y: null,\n        height: 600,\n        width: 800,\n    },\n    isMaximized: false,\n}\n\nfunction storeWindowState(main) {\n    Log.info(\"storeWindowState called\")\n    if (!main) {\n        return\n    }\n\n    windowState.isMaximized = main.isMaximized()\n\n    if (!windowState.isMaximized) {\n        // only update bounds if window isn't maximized\n        windowState.bounds = main.getBounds()\n    }\n    try {\n        Log.info(\"Starting to persist settings...\")\n        PersistentSettings.set(\"_internal.windowState\", windowState as any)\n        Log.info(\"Completed setting persisted settings\")\n    } catch (e) {\n        Log.info(`error setting window state: ${e.message}`)\n    }\n}\n\nipcMain.on(\"focus-next-instance\", () => {\n    Log.info(\"focus-next-instance\")\n    focusNextInstance(1)\n})\n\nipcMain.on(\"focus-previous-instance\", () => {\n    Log.info(\"focus-previous-instance\")\n    focusNextInstance(-1)\n})\n\nipcMain.on(\"move-to-next-oni-instance\", (event, direction: string) => {\n    Log.info(`Attempting to swap to Oni instance on the ${direction}.`)\n    moveToNextOniInstance(windows, direction)\n})\n\nipcMain.on(\"open-oni-window\", () => {\n    Log.info(\"opening window\")\n    createWindow([], process.cwd())\n})\n\n// Keep a global reference of the window object, if you don't, the window will\n// be closed automatically when the JavaScript object is garbage collected.\nlet windows: BrowserWindow[] = []\nconst activeWindow = () => {\n    return windows.filter(w => w.isFocused())[0] || null\n}\n\n// Only enable 'single-instance' mode when we're not in the hot-reload mode\n// Otherwise, all other open instances will also pick up the webpack bundle\nif (!isDevelopment && !isDebug && !isAutomation) {\n    const currentOptions = {\n        args: processArgs,\n        workingDirectory: process.env[\"ONI_CWD\"] || process.cwd(), // tslint:disable-line no-string-literal\n    }\n\n    Log.info(\"Making single instance...\")\n    makeSingleInstance(currentOptions, options => {\n        Log.info(\"Creating single instance\")\n        loadFileFromArguments(process.platform, options.args, options.workingDirectory)\n    })\n} else {\n    // If running from spectron, ignore the arguments\n    let argsToUse = processArgs\n    if (isAutomation) {\n        Log.warn(\"Clearing arguments because running from automation!\")\n        argsToUse = []\n    }\n\n    // This method will be called when Electron has finished\n    // initialization and is ready to create browser windows.\n    // Some APIs can only be used after this event occurs.\n    app.on(\"ready\", async () => {\n        if (!isAutomation) {\n            await addDevExtensions()\n        }\n        loadFileFromArguments(process.platform, argsToUse, process.env.ONI_CWD || process.cwd())\n    })\n}\n\nexport interface IDelayedEvent {\n    evt: string\n    cmd: Array<string | string[]>\n}\n\nexport function createWindow(\n    commandLineArguments,\n    workingDirectory,\n    delayedEvent: IDelayedEvent = null,\n) {\n    Log.info(\n        `Creating window with arguments: ${commandLineArguments} and working directory: ${workingDirectory}`,\n    )\n    const webPreferences = {\n        blinkFeatures: \"ResizeObserver,Accelerated2dCanvas,Canvas2dFixedRenderingMode\",\n    }\n\n    const backgroundColor =\n        (PersistentSettings.get(\"_internal.lastBackgroundColor\") as string) || \"#1E2127\"\n\n    try {\n        const internalWindowState = PersistentSettings.get(\"_internal.windowState\") as IWindowState\n        if (\n            internalWindowState &&\n            (internalWindowState.bounds || internalWindowState.isMaximized)\n        ) {\n            windowState = internalWindowState\n        }\n    } catch (e) {\n        Log.info(`error getting window state: ${e.message}`)\n    }\n\n    const rootPath = path.join(__dirname, \"..\", \"..\", \"..\")\n    const iconImage = process.platform === \"win32\" ? \"oni.ico\" : \"256x256.png\"\n    const iconPath = path.join(rootPath, \"images\", iconImage)\n\n    const indexFileName = isDevelopment ? \"index.dev.html\" : \"index.html\"\n    const indexPath = path.join(rootPath, indexFileName + \"?react_perf\")\n    // Create the browser window.\n    // TODO: Do we need to use non-ico for other platforms?\n    let currentWindow = new BrowserWindow({\n        icon: iconPath,\n        webPreferences,\n        backgroundColor,\n        titleBarStyle: \"hidden\",\n        x: windowState.bounds.x,\n        y: windowState.bounds.y,\n        height: windowState.bounds.height,\n        width: windowState.bounds.width,\n    })\n\n    // Workaround for cut/copy/paste/close keybindings not working in devtools window on OSX\n    if (process.platform === \"darwin\") {\n        currentWindow.webContents.on(\"devtools-opened\", () => {\n            currentWindow.webContents.devToolsWebContents.executeJavaScript(`\n                window.addEventListener('keydown', function (e) {\n                    if (e.keyCode === 65 && e.metaKey) {\n                        document.execCommand('Select All');\n                    } else if (e.keyCode === 67 && e.metaKey) {\n                        document.execCommand('copy');\n                    } else if (e.keyCode === 86 && e.metaKey) {\n                        document.execCommand('paste');\n                    } else if (e.keyCode === 87 && e.metaKey) {\n                        window.close();\n                    } else if (e.keyCode === 88 && e.metaKey) {\n                        document.execCommand('cut');\n                    }\n                });`)\n        })\n    }\n\n    if (windowState.isMaximized) {\n        currentWindow.maximize()\n    }\n\n    updateMenu(currentWindow, false)\n    currentWindow.webContents.on(\"did-finish-load\", () => {\n        Log.info(\"did-finish-load event received\")\n        currentWindow.webContents.send(\"init\", {\n            args: commandLineArguments,\n            workingDirectory,\n        })\n    })\n\n    ipcMain.once(\"Oni.started\", evt => {\n        Log.info(\"Oni started\")\n\n        if (delayedEvent) {\n            currentWindow.webContents.send(delayedEvent.evt, ...delayedEvent.cmd)\n        }\n    })\n\n    ipcMain.on(\"rebuild-menu\", (_evt, loadInit) => {\n        // ipcMain is a singleton so if there are multiple Oni instances\n        // we may receive an event from a different instance\n        if (currentWindow) {\n            updateMenu(currentWindow, loadInit)\n        }\n    })\n\n    // and load the index.html of the app.\n    currentWindow.loadURL(`file://${indexPath}`)\n\n    // Open the DevTools.\n    if (process.env.NODE_ENV === \"development\" || commandLineArguments.indexOf(\"--debug\") >= 0) {\n        currentWindow.webContents.openDevTools()\n    }\n\n    currentWindow.on(\"move\", () => {\n        storeWindowState(currentWindow)\n    })\n    currentWindow.on(\"resize\", () => {\n        storeWindowState(currentWindow)\n    })\n    currentWindow.on(\"close\", () => {\n        Log.info(\"close event...\")\n        storeWindowState(currentWindow)\n        Log.info(\"...close event completed\")\n    })\n\n    // Emitted when the window is closed.\n    currentWindow.on(\"closed\", () => {\n        Log.info(\"closed event...\")\n        // Dereference the window object, usually you would store windows\n        // in an array if your app supports multi windows, this is the time\n        // when you should delete the corresponding element.\n        windows = windows.filter(m => m !== currentWindow)\n        currentWindow = null\n        Log.info(\"...closed event completed\")\n    })\n\n    if (!isDevelopment) {\n        currentWindow.webContents.on(\"will-navigate\", (event, url) => {\n            event.preventDefault()\n            currentWindow.webContents.send(\"execute-command\", \"browser.openUrl\", url)\n        })\n    }\n\n    windows.push(currentWindow)\n\n    return currentWindow\n}\n\napp.on(\"open-file\", (event, filePath) => {\n    event.preventDefault()\n    Log.info(`filePath to open: ${filePath}`)\n    if (activeWindow()) {\n        activeWindow().webContents.send(\"open-file\", filePath)\n    } else if (process.platform.includes(\"darwin\")) {\n        const argsToUse = [...process.argv.slice(1), filePath]\n\n        if (app.isReady()) {\n            createWindow(argsToUse, process.cwd())\n        } else {\n            app.on(\"ready\", () => {\n                createWindow(argsToUse, process.cwd())\n            })\n        }\n    }\n})\n\n// Quit when all windows are closed.\napp.on(\"window-all-closed\", () => {\n    Log.info(\"window-all-closed event\")\n    // On OS X it is common for applications and their menu bar\n    // to stay active until the user quits explicitly with Cmd + Q\n    if (process.platform !== \"darwin\" || isAutomation) {\n        Log.info(\"quitting app\")\n        app.quit()\n    }\n})\n\napp.on(\"activate\", () => {\n    // On OS X it's common to re-create a window in the app when the\n    // dock icon is clicked and there are no other windows open.\n    if (!windows.length) {\n        createWindow([], process.cwd())\n    }\n    if (activeWindow()) {\n        activeWindow().show()\n    }\n})\n\nfunction updateMenu(browserWindow, loadInit) {\n    const menu = buildMenu(browserWindow, loadInit)\n    if (process.platform === \"darwin\") {\n        // all osx windows share the same menu\n        Menu.setApplicationMenu(menu)\n        const dockMenu = buildDockMenu(browserWindow, loadInit)\n        app.dock.setMenu(dockMenu)\n    } else {\n        // on windows and linux, set menu per window\n        browserWindow.setMenu(menu)\n    }\n}\n\nfunction focusNextInstance(direction) {\n    const currentFocusedWindows = windows.filter(f => f.isFocused())\n\n    if (currentFocusedWindows.length === 0) {\n        Log.info(\"No window currently focused\")\n        return\n    }\n\n    const currentFocusedWindow = currentFocusedWindows[0]\n    const currentWindowIdx = windows.indexOf(currentFocusedWindow)\n    let newFocusWindowIdx = (currentWindowIdx + direction) % windows.length\n\n    if (newFocusWindowIdx < 0) {\n        newFocusWindowIdx = windows.length - 1\n    }\n\n    Log.info(`Focusing index: ${newFocusWindowIdx}`)\n    windows[newFocusWindowIdx].focus()\n}\n\nfunction loadFileFromArguments(platform, args, workingDirectory) {\n    const localOni = \"LOCAL_ONI\"\n    if (!process.env[localOni]) {\n        createWindow(args.slice(1), workingDirectory)\n    } else {\n        createWindow(args.slice(2), workingDirectory)\n    }\n}\n// In this file you can include the rest of your app's specific main process\n// code. You can also put them in separate files and require them here.\n"
  },
  {
    "path": "main/src/menu.ts",
    "content": "import * as os from \"os\"\n\nimport { app, BrowserWindow, dialog, Menu } from \"electron\"\nimport { createWindow, IDelayedEvent } from \"./main\"\n\nexport const buildDockMenu = (mainWindow, loadInit) => {\n    const menu = []\n    menu.push({\n        label: \"New Window\",\n        click() {\n            createWindow([], process.cwd())\n        },\n    })\n\n    return Menu.buildFromTemplate(menu)\n}\n\nexport const buildMenu = (mainWindow, loadInit) => {\n    const menu = []\n\n    // On Windows, both the forward slash `/` and the backward slash `\\` are accepted as path delimiters.\n    // The node APIs only return the backward slash, ie: `C:\\\\oni\\\\README.md`, but this causes problems\n    // for VIM as it sees escape keys.\n\n    const executeMenuAction = (browserWindow: BrowserWindow, delayedEvent: IDelayedEvent) => {\n        if (browserWindow) {\n            return browserWindow.webContents.send(delayedEvent.evt, ...delayedEvent.cmd)\n        }\n        createWindow([], process.cwd(), delayedEvent)\n    }\n\n    const normalizePath = fileName => fileName.split(\"\\\\\").join(\"/\")\n\n    const executeVimCommand = (browserWindow: BrowserWindow, command: string) => {\n        executeMenuAction(browserWindow, {\n            evt: \"execute-command\",\n            cmd: [\"editor.executeVimCommand\", command],\n        })\n    }\n\n    const openMultipleFiles = (browserWindow: BrowserWindow, files: string[]) => {\n        executeMenuAction(browserWindow, { evt: \"open-files\", cmd: [files] })\n    }\n\n    const executeOniCommand = (browserWindow: BrowserWindow, command: string) => {\n        executeMenuAction(browserWindow, { evt: \"execute-command\", cmd: [command] })\n    }\n\n    const openUrl = (browserWindow: BrowserWindow, url: string) => {\n        executeMenuAction(browserWindow, { evt: \"execute-command\", cmd: [\"browser.openUrl\", url] })\n    }\n\n    const executeVimCommandForFiles = (browserWindow, command, files) => {\n        if (!files || !files.length) {\n            return\n        }\n\n        files.forEach(fileName =>\n            executeVimCommand(browserWindow, `${command} ${normalizePath(fileName)}`),\n        )\n    }\n\n    const isWindows = os.platform() === \"win32\"\n\n    const preferences = {\n        label: \"Preferences\",\n        submenu: [\n            {\n                label: \"Edit Oni config\",\n                accelerator: \"CmdOrCtrl+,\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"oni.config.openConfigJs\")\n                },\n            },\n        ],\n    }\n\n    if (loadInit) {\n        preferences.submenu.push({\n            label: \"Edit Neovim config\",\n            accelerator: null,\n            click(item, focusedWindow) {\n                executeOniCommand(focusedWindow, \"oni.config.openInitVim\")\n            },\n        })\n    }\n\n    const reopenWithEncoding = {\n        label: \"Reopen with Encoding\",\n        submenu: [],\n    }\n\n    // TODO: Maybe better show normal encoding name in submenu?\n    // Encoding list from http://vimdoc.sourceforge.net/htmldoc/mbyte.html#encoding-values\n    const encodingList = [\n        \"utf-8\",\n        \"utf-16le\",\n        \"utf-16be\",\n        \"utf-32le\",\n        \"utf-32be\",\n        \"latin1\",\n        \"koi8-r\",\n        \"koi8-u\",\n        \"macroman\",\n        \"cp437\",\n        \"cp737\",\n        \"cp775\",\n        \"cp850\",\n        \"cp852\",\n        \"cp855\",\n        \"cp857\",\n        \"cp860\",\n        \"cp861\",\n        \"cp862\",\n        \"cp863\",\n        \"cp865\",\n        \"cp866\",\n        \"cp869\",\n        \"cp874\",\n        \"cp1250\",\n        \"cp1251\",\n        \"cp1253\",\n        \"cp1254\",\n        \"cp1255\",\n        \"cp1256\",\n        \"cp1257\",\n        \"cp1258\",\n        \"cp932\",\n        \"euc-jp\",\n        \"sjis\",\n        \"cp949\",\n        \"euc-kr\",\n        \"cp936\",\n        \"euc-cn\",\n        \"cp950\",\n        \"big5\",\n        \"euc-tw\",\n    ].map(val => {\n        return {\n            label: val.toUpperCase(),\n            click(item, focusedWindow) {\n                executeVimCommand(focusedWindow, \":e! ++enc=\" + val)\n            },\n        }\n    })\n\n    reopenWithEncoding.submenu.push(...encodingList)\n\n    menu.push({\n        label: isWindows ? \"File\" : \"Oni\",\n        submenu: [\n            {\n                label: \"New File\",\n                accelerator: \"CmdOrCtrl+N\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \":enew\")\n                },\n            },\n            {\n                label: \"Open File…\",\n                accelerator: \"CmdOrCtrl+O\",\n                click(item, focusedWindow) {\n                    dialog.showOpenDialog(\n                        focusedWindow,\n                        { properties: [\"openFile\", \"multiSelections\"] },\n                        files => openMultipleFiles(focusedWindow, files),\n                    )\n                },\n            },\n            {\n                label: \"Open Folder…\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"workspace.openFolder\")\n                },\n            },\n            reopenWithEncoding,\n            {\n                label: \"Split Open…\",\n                click(item, focusedWindow) {\n                    dialog.showOpenDialog(focusedWindow, { properties: [\"openFile\"] }, files =>\n                        executeVimCommandForFiles(focusedWindow, \":sp\", files),\n                    )\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"New Window\",\n                click() {\n                    createWindow([], process.cwd())\n                },\n            },\n            {\n                label: \"Hide Window\",\n                click(item, focusedWindow) {\n                    focusedWindow.hide()\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Save\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \":w\")\n                },\n            },\n            {\n                label: \"Save As…\",\n                click(item, focusedWindow) {\n                    dialog.showSaveDialog(focusedWindow, {}, name => {\n                        if (name) {\n                            executeVimCommand(focusedWindow, \":save \" + normalizePath(name))\n                        }\n                    })\n                },\n            },\n            {\n                label: \"Save All\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \":wall\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            preferences,\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Close File\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \":close\")\n                },\n            },\n            {\n                label: \"Revert File\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \":e!\")\n                },\n            },\n            {\n                label: \"Close All File\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \":%bw\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Exit\",\n                accelerator: \"CmdOrCtrl+Q\",\n                click(item, focusedWindow) {\n                    app.quit()\n                },\n            },\n        ],\n    })\n\n    // Edit menu\n    menu.push({\n        label: \"Edit\",\n        submenu: [\n            {\n                label: \"Undo\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"u\")\n                },\n            },\n            {\n                label: \"Redo\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-r>\")\n                },\n            },\n            {\n                label: \"Repeat\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \".\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Copy\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"editor.clipboard.yank\")\n                },\n            },\n            {\n                label: \"Cut\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"editor.clipboard.cut\")\n                },\n            },\n            {\n                label: \"Paste\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"editor.clipboard.paste\")\n                },\n            },\n            {\n                label: \"Paste Line Before\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"[p\")\n                },\n            },\n            {\n                label: \"Paste Line After\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"]p\")\n                },\n            },\n            {\n                label: \"Copy File Path\",\n                submenu: [\n                    {\n                        label: \"Full Path\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":let @\" + (isWindows ? \"*\" : \"+\") + \"=expand('%:p')\",\n                            )\n                        },\n                    },\n                    {\n                        label: \"Full Path with Line Number\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":let @\" +\n                                    (isWindows ? \"*\" : \"+\") +\n                                    \"=expand('%:p') . ':' . line('.')\",\n                            )\n                        },\n                    },\n                    {\n                        label: \"Relative Path\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":let @\" + (isWindows ? \"*\" : \"+\") + \"=expand('%')\",\n                            )\n                        },\n                    },\n                    {\n                        label: \"Relative Path with Line Number\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":let @\" +\n                                    (isWindows ? \"*\" : \"+\") +\n                                    \"=expand('%') . ':' . line('.')\",\n                            )\n                        },\n                    },\n                    {\n                        label: \"File Name\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":let @\" + (isWindows ? \"*\" : \"+\") + \"=expand('%:t')\",\n                            )\n                        },\n                    },\n                    {\n                        label: \"File Name with Line Number\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":let @\" +\n                                    (isWindows ? \"*\" : \"+\") +\n                                    \"=expand('%:t') . ':' . line('.')\",\n                            )\n                        },\n                    },\n                ],\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Line\",\n                submenu: [\n                    {\n                        label: \"Indent\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \">\")\n                        },\n                    },\n                    {\n                        label: \"Unindent\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"<\")\n                        },\n                    },\n                    {\n                        label: \"Reindent\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"=i{\")\n                        },\n                    },\n                    {\n                        type: \"separator\",\n                    },\n                    {\n                        label: \"Move Up\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"m+\")\n                        },\n                    },\n                    {\n                        label: \"Move Down\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"m--\")\n                        },\n                    },\n                    {\n                        type: \"separator\",\n                    },\n                    {\n                        label: \"Duplicate\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"Yp\")\n                        },\n                    },\n                    {\n                        label: \"Copy\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"Y\")\n                        },\n                    },\n                    {\n                        label: \"Cut\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"Y^D\")\n                        },\n                    },\n                    {\n                        label: \"Delete\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"dd\")\n                        },\n                    },\n                    {\n                        label: \"Clear\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"^D\")\n                        },\n                    },\n                    {\n                        label: \"Join\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"J\")\n                        },\n                    },\n                ],\n            },\n            {\n                label: \"Text\",\n                submenu: [\n                    {\n                        label: \"Upper Case\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"U\")\n                        },\n                    },\n                    {\n                        label: \"Lower Case\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"u\")\n                        },\n                    },\n                    {\n                        label: \"Swap Case\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"~\")\n                        },\n                    },\n                    {\n                        type: \"separator\",\n                    },\n                    {\n                        label: \"Delete Inner Word\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"diw\")\n                        },\n                    },\n                    {\n                        label: \"Delete Previous Word\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"bbdw\")\n                        },\n                    },\n                    {\n                        label: \"Delete Next Word\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"nwdw\")\n                        },\n                    },\n                    {\n                        label: \"Strip First Character\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":%normal ^x\")\n                        },\n                    },\n                    {\n                        label: \"Strip Last Character\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":%normal $x\")\n                        },\n                    },\n                    {\n                        label: \"Strip Trailings Blanks\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":%s/^s+//\")\n                            executeVimCommand(focusedWindow, \":%s/s+$//\")\n                        },\n                    },\n                    {\n                        label: \"Delete Line\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"dd\")\n                        },\n                    },\n                    {\n                        label: \"Remove Blank Lines\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":g/^$/d\")\n                        },\n                    },\n                ],\n            },\n            {\n                label: \"Comment\",\n                submenu: [\n                    {\n                        label: \"Toggle Comment\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":Commentary\")\n                        },\n                    },\n                ],\n            },\n            {\n                label: \"Insert\",\n                submenu: [\n                    {\n                        label: \"Encoding Identifier\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":put =&fileencoding\")\n                        },\n                    },\n                    {\n                        type: \"separator\",\n                    },\n                    {\n                        label: \"Date / Time (Short)\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":put =strftime('%c')\")\n                        },\n                    },\n                    {\n                        label: \"Date / Time (Long)\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":put =strftime('%a, %d %b %Y %H:%M:%S')\",\n                            )\n                        },\n                    },\n                    {\n                        type: \"separator\",\n                    },\n                    {\n                        label: \"Full Path\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":put =expand('%:p')\")\n                        },\n                    },\n                    {\n                        label: \"File Name\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \":put =expand('%:t')\")\n                        },\n                    },\n                    {\n                        label: \"File Name with Line Number\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(\n                                focusedWindow,\n                                \":put =expand('%:t') . ':' . line('.')\",\n                            )\n                        },\n                    },\n                ],\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Select All\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"ggVG\")\n                },\n            },\n        ],\n    })\n\n    // Window menu\n    menu.push({\n        label: \"Split\",\n        submenu: [\n            {\n                label: \"New Horizontal Split\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>n\")\n                },\n            },\n            {\n                label: \"Split File Horizontally\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>s\")\n                },\n            },\n            {\n                label: \"Split File Vertically\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>v\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Close\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>c\")\n                },\n            },\n            {\n                label: \"Close Other Split(s)\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>o\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Move To\",\n                submenu: [\n                    {\n                        label: \"Top\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"\\\\<C-w>K\")\n                        },\n                    },\n                    {\n                        label: \"Bottom\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"\\\\<C-w>J\")\n                        },\n                    },\n                    {\n                        label: \"Left Side\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"\\\\<C-w>H\")\n                        },\n                    },\n                    {\n                        label: \"Right Side\",\n                        click(item, focusedWindow) {\n                            executeVimCommand(focusedWindow, \"\\\\<C-w>L\")\n                        },\n                    },\n                ],\n            },\n            {\n                label: \"Rotate Up\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>R\")\n                },\n            },\n            {\n                label: \"Rotate Down\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>r\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Equal Size\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>=\")\n                },\n            },\n            {\n                label: \"Max Height\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>_\")\n                },\n            },\n            {\n                label: \"Min Height\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>1_\")\n                },\n            },\n            {\n                label: \"Max Width\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>|\")\n                },\n            },\n            {\n                label: \"Min Width\",\n                click(item, focusedWindow) {\n                    executeVimCommand(focusedWindow, \"\\\\<C-w>1|\")\n                },\n            },\n        ],\n    })\n\n    // Help menu\n    menu.push({\n        label: \"Help\",\n        submenu: [\n            {\n                label: \"Learn more\",\n                click(item, focusedWindow) {\n                    openUrl(focusedWindow, \"https://github.com/onivim/oni#introduction\")\n                },\n            },\n            {\n                label: \"Issues\",\n                click(item, focusedWindow) {\n                    openUrl(focusedWindow, \"https://github.com/onivim/oni/issues\")\n                },\n            },\n            {\n                label: \"GitHub\",\n                sublabel: \"https://github.com/onivim/oni\",\n                click(item, focusedWindow) {\n                    openUrl(focusedWindow, \"https://github.com/onivim/oni\")\n                },\n            },\n            {\n                label: \"Website\",\n                sublabel: \"https://www.onivim.io\",\n                click(item, focusedWindow) {\n                    openUrl(focusedWindow, \"https://www.onivim.io\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"About Oni\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"oni.about\")\n                },\n            },\n            {\n                type: \"separator\",\n            },\n            {\n                label: \"Developer Tools\",\n                click(item, focusedWindow) {\n                    executeOniCommand(focusedWindow, \"oni.debug.openDevTools\")\n                },\n            },\n        ],\n    })\n\n    return Menu.buildFromTemplate(menu)\n}\n"
  },
  {
    "path": "main/test/WindowManagerTests.ts",
    "content": "/**\n * WindowManagerTests.ts\n */\n\nimport * as assert from \"assert\"\nimport {\n    checkWindowToFindBest,\n    compareDistances,\n    DistanceComparison,\n    windowIsInValidDirection,\n} from \"./../src/WindowManager\"\nimport { Rectangle } from \"electron\"\n\ndescribe(\"checkWindowToFindBest\", () => {\n    it(\"Correctly accepts better window on X axis.\", async () => {\n        const currentWindow = { x: 0, y: 0 } as Rectangle\n        const testWindow = { x: 100, y: 0 } as Rectangle\n        const bestWindow = { x: 150, y: 0 } as Rectangle\n        const direction = \"right\"\n\n        const result = checkWindowToFindBest(currentWindow, testWindow, bestWindow, direction)\n        assert.equal(result, true)\n    })\n    it(\"Correctly accepts better window on Y axis.\", async () => {\n        const currentWindow = { x: 0, y: 0 } as Rectangle\n        const testWindow = { x: 0, y: 100 } as Rectangle\n        const bestWindow = { x: 0, y: 150 } as Rectangle\n        const direction = \"down\"\n\n        const result = checkWindowToFindBest(currentWindow, testWindow, bestWindow, direction)\n        assert.equal(result, true)\n    })\n    it(\"Correctly rejects worse window on X axis.\", async () => {\n        const currentWindow = { x: 150, y: 0 } as Rectangle\n        const testWindow = { x: 0, y: 0 } as Rectangle\n        const bestWindow = { x: 100, y: 0 } as Rectangle\n        const direction = \"left\"\n\n        const result = checkWindowToFindBest(currentWindow, testWindow, bestWindow, direction)\n        assert.equal(result, false)\n    })\n    it(\"Correctly rejects worse window on Y axis.\", async () => {\n        const currentWindow = { x: 0, y: 150 } as Rectangle\n        const testWindow = { x: 0, y: 50 } as Rectangle\n        const bestWindow = { x: 0, y: 100 } as Rectangle\n        const direction = \"up\"\n\n        const result = checkWindowToFindBest(currentWindow, testWindow, bestWindow, direction)\n        assert.equal(result, false)\n    })\n})\ndescribe(\"compareDistance\", () => {\n    it(\"Correctly returns lower.\", async () => {\n        const currentDiff = 10\n        const bestDiff = 100\n\n        const result = compareDistances(currentDiff, bestDiff)\n        assert.equal(result, DistanceComparison.smaller)\n    })\n    it(\"Correctly returns higher.\", async () => {\n        const currentDiff = 100\n        const bestDiff = 10\n\n        const result = compareDistances(currentDiff, bestDiff)\n        assert.equal(result, DistanceComparison.larger)\n    })\n    it(\"Correctly returns equal.\", async () => {\n        const currentDiff = 10\n        const bestDiff = 10\n\n        const result = compareDistances(currentDiff, bestDiff)\n        assert.equal(result, DistanceComparison.equal)\n    })\n})\ndescribe(\"windowIsInValidDirection\", () => {\n    it(\"Correctly accepts window in X axis.\", async () => {\n        const currentWindow = { x: 0, y: 0 } as Rectangle\n        const testWindow = { x: 100, y: 0 } as Rectangle\n        const direction = \"right\"\n\n        const result = windowIsInValidDirection(direction, currentWindow, testWindow)\n        assert.equal(result, true)\n    })\n    it(\"Correctly accepts window in Y axis.\", async () => {\n        const currentWindow = { x: 0, y: 0 } as Rectangle\n        const testWindow = { x: 0, y: 100 } as Rectangle\n        const direction = \"down\"\n\n        const result = windowIsInValidDirection(direction, currentWindow, testWindow)\n        assert.equal(result, true)\n    })\n    it(\"Correctly rejects window in X axis.\", async () => {\n        const currentWindow = { x: 50, y: 0 } as Rectangle\n        const testWindow = { x: 100, y: 0 } as Rectangle\n        const direction = \"left\"\n\n        const result = windowIsInValidDirection(direction, currentWindow, testWindow)\n        assert.equal(result, false)\n    })\n    it(\"Correctly rejects window in Y axis.\", async () => {\n        const currentWindow = { x: 0, y: 50 } as Rectangle\n        const testWindow = { x: 0, y: 100 } as Rectangle\n        const direction = \"up\"\n\n        const result = windowIsInValidDirection(direction, currentWindow, testWindow)\n        assert.equal(result, false)\n    })\n})\n"
  },
  {
    "path": "main/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowUnreachableCode\": false,\n        \"allowUnusedLabels\": false,\n        \"experimentalDecorators\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"newLine\": \"LF\",\n        \"noEmitOnError\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"noImplicitReturns\": true,\n        \"noImplicitThis\": true,\n        \"noUnusedLocals\": true,\n        \"outDir\": \"../lib/main\",\n        \"pretty\": true,\n        \"removeComments\": true,\n        \"rootDir\": \".\",\n        \"skipLibCheck\": true,\n        \"strictNullChecks\": false,\n        \"suppressImplicitAnyIndexErrors\": true,\n        \"target\": \"es2015\",\n        \"sourceMap\": true\n    },\n    \"include\": [\"src/**/*.ts\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "main/tsconfig.test.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowUnreachableCode\": false,\n        \"allowUnusedLabels\": false,\n        \"experimentalDecorators\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"newLine\": \"LF\",\n        \"noEmitOnError\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"noImplicitReturns\": true,\n        \"noImplicitThis\": true,\n        \"noUnusedLocals\": true,\n        \"outDir\": \"../lib_test/main\",\n        \"pretty\": true,\n        \"removeComments\": true,\n        \"rootDir\": \".\",\n        \"skipLibCheck\": true,\n        \"strictNullChecks\": false,\n        \"suppressImplicitAnyIndexErrors\": true,\n        \"target\": \"es2015\",\n        \"sourceMap\": true\n    },\n    \"include\": [\"test/**/*.ts\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"oni\",\n    \"author\": \"\",\n    \"email\": \"bryphe@outlook.com\",\n    \"homepage\": \"https://www.onivim.io\",\n    \"version\": \"0.3.10\",\n    \"description\": \"Code editor with a modern twist on modal editing - powered by neovim.\",\n    \"keywords\": [\n        \"vim\",\n        \"neovim\",\n        \"text\",\n        \"editor\",\n        \"ide\",\n        \"vim\"\n    ],\n    \"main\": \"./lib/main/src/main.js\",\n    \"bin\": {\n        \"oni\": \"./lib/cli/src/cli.js\",\n        \"oni-vim\": \"./lib/cli/src/cli.js\"\n    },\n    \"build\": {\n        \"asar\": false,\n        \"productName\": \"Oni\",\n        \"appId\": \"com.extropy.oni\",\n        \"files\": [\n            \"cli/${os}\",\n            \"configuration\",\n            \"extensions\",\n            \"font-awesome\",\n            \"images\",\n            \"lib\",\n            \"!lib/**/*.map\",\n            \"node_modules\",\n            \"!node_modules/oni-api\",\n            \"!node_modules/typescript\",\n            \"vim\",\n            \"index.html\",\n            \"preload.js\"\n        ],\n        \"extraResources\": [\n            {\n                \"from\": \"node_modules/oni-api\",\n                \"to\": \"app/node_modules/oni-api\"\n            },\n            {\n                \"from\": \"node_modules/typescript\",\n                \"to\": \"app/node_modules/typescript\"\n            }\n        ],\n        \"mac\": {\n            \"artifactName\": \"${productName}-${version}-osx.${ext}\",\n            \"category\": \"public.app-category.developer-tools\",\n            \"target\": [\n                \"dmg\"\n            ],\n            \"files\": [\n                \"bin/osx/**/*\"\n            ]\n        },\n        \"linux\": {\n            \"artifactName\": \"${productName}-${version}-${arch}-linux.${ext}\",\n            \"maintainer\": \"bryphe@outlook.com\",\n            \"target\": [\n                \"tar.gz\",\n                \"deb\",\n                \"rpm\"\n            ]\n        },\n        \"win\": {\n            \"target\": [\n                \"zip\",\n                \"dir\"\n            ],\n            \"files\": [\n                \"bin/x86/**/*\"\n            ]\n        },\n        \"fileAssociations\": [\n            {\n                \"name\": \"ADA source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"adb\",\n                    \"ads\"\n                ]\n            },\n            {\n                \"name\": \"Compiled AppleScript\",\n                \"role\": \"Editor\",\n                \"ext\": \"scpt\"\n            },\n            {\n                \"name\": \"AppleScript source\",\n                \"role\": \"Editor\",\n                \"ext\": \"applescript\"\n            },\n            {\n                \"name\": \"ActionScript source\",\n                \"role\": \"Editor\",\n                \"ext\": \"as\"\n            },\n            {\n                \"name\": \"ASP document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"asp\",\n                    \"asa\"\n                ]\n            },\n            {\n                \"name\": \"ASP.NET document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"aspx\",\n                    \"ascx\",\n                    \"asmx\",\n                    \"ashx\"\n                ]\n            },\n            {\n                \"name\": \"BibTeX bibliography\",\n                \"role\": \"Editor\",\n                \"ext\": \"bib\"\n            },\n            {\n                \"name\": \"C source\",\n                \"role\": \"Editor\",\n                \"ext\": \"c\"\n            },\n            {\n                \"name\": \"C++ source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"cc\",\n                    \"cp\",\n                    \"cpp\",\n                    \"cxx\",\n                    \"c++\"\n                ]\n            },\n            {\n                \"name\": \"C# source\",\n                \"role\": \"Editor\",\n                \"ext\": \"cs\"\n            },\n            {\n                \"name\": \"CoffeeScript source\",\n                \"role\": \"Editor\",\n                \"ext\": \"coffee\"\n            },\n            {\n                \"name\": \"Commit message\",\n                \"role\": \"Editor\",\n                \"ext\": \"COMMIT_EDITMSG\"\n            },\n            {\n                \"name\": \"Context Free Design Grammar\",\n                \"role\": \"Editor\",\n                \"ext\": \"cfdg\"\n            },\n            {\n                \"name\": \"Clojure source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"clj\",\n                    \"cljs\"\n                ]\n            },\n            {\n                \"name\": \"Comma separated values\",\n                \"role\": \"Editor\",\n                \"ext\": \"csv\"\n            },\n            {\n                \"name\": \"Tab separated values\",\n                \"role\": \"Editor\",\n                \"ext\": \"tsv\"\n            },\n            {\n                \"name\": \"CGI script\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"cgi\",\n                    \"fcgi\"\n                ]\n            },\n            {\n                \"name\": \"Configuration file\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"cfg\",\n                    \"conf\",\n                    \"config\",\n                    \"htaccess\"\n                ]\n            },\n            {\n                \"name\": \"Cascading style sheet\",\n                \"role\": \"Editor\",\n                \"ext\": \"css\"\n            },\n            {\n                \"name\": \"Differences file\",\n                \"role\": \"Editor\",\n                \"ext\": \"diff\"\n            },\n            {\n                \"name\": \"Document Type Definition\",\n                \"role\": \"Editor\",\n                \"ext\": \"dtd\"\n            },\n            {\n                \"name\": \"Dylan source\",\n                \"role\": \"Editor\",\n                \"ext\": \"dylan\"\n            },\n            {\n                \"name\": \"Erlang source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"erl\",\n                    \"hrl\"\n                ]\n            },\n            {\n                \"name\": \"F-Script source\",\n                \"role\": \"Editor\",\n                \"ext\": \"fscript\"\n            },\n            {\n                \"name\": \"Fortran source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"f\",\n                    \"for\",\n                    \"fpp\",\n                    \"f77\",\n                    \"f90\",\n                    \"f95\"\n                ]\n            },\n            {\n                \"name\": \"Header\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"h\",\n                    \"pch\"\n                ]\n            },\n            {\n                \"name\": \"C++ header\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"hh\",\n                    \"hpp\",\n                    \"hxx\",\n                    \"h++\"\n                ]\n            },\n            {\n                \"name\": \"Go source\",\n                \"role\": \"Editor\",\n                \"ext\": \"go\"\n            },\n            {\n                \"name\": \"GTD document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"gtd\",\n                    \"gtdlog\"\n                ]\n            },\n            {\n                \"name\": \"Haskell source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"hs\",\n                    \"lhs\"\n                ]\n            },\n            {\n                \"name\": \"HTML document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"htm\",\n                    \"html\",\n                    \"phtml\",\n                    \"shtml\"\n                ]\n            },\n            {\n                \"name\": \"Include file\",\n                \"role\": \"Editor\",\n                \"ext\": \"inc\"\n            },\n            {\n                \"name\": \"iCalendar schedule\",\n                \"role\": \"Editor\",\n                \"ext\": \"ics\"\n            },\n            {\n                \"name\": \"MS Windows initialization file\",\n                \"role\": \"Editor\",\n                \"ext\": \"ini\"\n            },\n            {\n                \"name\": \"Io source\",\n                \"role\": \"Editor\",\n                \"ext\": \"io\"\n            },\n            {\n                \"name\": \"Java source\",\n                \"role\": \"Editor\",\n                \"ext\": \"java\"\n            },\n            {\n                \"name\": \"BeanShell script\",\n                \"role\": \"Editor\",\n                \"ext\": \"bsh\"\n            },\n            {\n                \"name\": \"Java properties file\",\n                \"role\": \"Editor\",\n                \"ext\": \"properties\"\n            },\n            {\n                \"name\": \"JavaScript source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"js\",\n                    \"htc\"\n                ]\n            },\n            {\n                \"name\": \"Java Server Page\",\n                \"role\": \"Editor\",\n                \"ext\": \"jsp\"\n            },\n            {\n                \"name\": \"JSON file\",\n                \"role\": \"Editor\",\n                \"ext\": \"json\"\n            },\n            {\n                \"name\": \"LDAP Data Interchange Format\",\n                \"role\": \"Editor\",\n                \"ext\": \"ldif\"\n            },\n            {\n                \"name\": \"Less source\",\n                \"role\": \"Editor\",\n                \"ext\": \"less\"\n            },\n            {\n                \"name\": \"Lisp source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"lisp\",\n                    \"cl\",\n                    \"l\",\n                    \"lsp\",\n                    \"mud\",\n                    \"el\"\n                ]\n            },\n            {\n                \"name\": \"Log file\",\n                \"role\": \"Editor\",\n                \"ext\": \"log\"\n            },\n            {\n                \"name\": \"Logo source\",\n                \"role\": \"Editor\",\n                \"ext\": \"logo\"\n            },\n            {\n                \"name\": \"Lua source\",\n                \"role\": \"Editor\",\n                \"ext\": \"lua\"\n            },\n            {\n                \"name\": \"Markdown document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"markdown\",\n                    \"mdown\",\n                    \"markdn\",\n                    \"md\"\n                ]\n            },\n            {\n                \"name\": \"Makefile source\",\n                \"role\": \"Editor\",\n                \"ext\": \"mk\"\n            },\n            {\n                \"name\": \"Mediawiki document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"wiki\",\n                    \"wikipedia\",\n                    \"mediawiki\"\n                ]\n            },\n            {\n                \"name\": \"MIPS assembler source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"s\",\n                    \"mips\",\n                    \"spim\",\n                    \"asm\"\n                ]\n            },\n            {\n                \"name\": \"Modula-3 source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"m3\",\n                    \"cm3\"\n                ]\n            },\n            {\n                \"name\": \"MoinMoin document\",\n                \"role\": \"Editor\",\n                \"ext\": \"moinmoin\"\n            },\n            {\n                \"name\": \"Objective-C source\",\n                \"role\": \"Editor\",\n                \"ext\": \"m\"\n            },\n            {\n                \"name\": \"Objective-C++ source\",\n                \"role\": \"Editor\",\n                \"ext\": \"mm\"\n            },\n            {\n                \"name\": \"OCaml source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"ml\",\n                    \"mli\",\n                    \"mll\",\n                    \"mly\"\n                ]\n            },\n            {\n                \"name\": \"Mustache document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"mustache\",\n                    \"hbs\"\n                ]\n            },\n            {\n                \"name\": \"Pascal source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"pas\",\n                    \"p\"\n                ]\n            },\n            {\n                \"name\": \"Patch file\",\n                \"role\": \"Editor\",\n                \"ext\": \"patch\"\n            },\n            {\n                \"name\": \"Perl source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"pl\",\n                    \"pod\",\n                    \"perl\"\n                ]\n            },\n            {\n                \"name\": \"Perl module\",\n                \"role\": \"Editor\",\n                \"ext\": \"pm\"\n            },\n            {\n                \"name\": \"PHP source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"php\",\n                    \"php3\",\n                    \"php4\",\n                    \"php5\"\n                ]\n            },\n            {\n                \"name\": \"PostScript source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"ps\",\n                    \"eps\"\n                ]\n            },\n            {\n                \"name\": \"Property list\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"dict\",\n                    \"plist\",\n                    \"scriptSuite\",\n                    \"scriptTerminology\"\n                ]\n            },\n            {\n                \"name\": \"Python source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"py\",\n                    \"rpy\",\n                    \"cpy\",\n                    \"python\"\n                ]\n            },\n            {\n                \"name\": \"R source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"r\",\n                    \"s\"\n                ]\n            },\n            {\n                \"name\": \"Ragel source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"rl\",\n                    \"ragel\"\n                ]\n            },\n            {\n                \"name\": \"Remind document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"rem\",\n                    \"remind\"\n                ]\n            },\n            {\n                \"name\": \"reStructuredText document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"rst\",\n                    \"rest\"\n                ]\n            },\n            {\n                \"name\": \"HTML with embedded Ruby\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"rhtml\",\n                    \"erb\"\n                ]\n            },\n            {\n                \"name\": \"SQL with embedded Ruby\",\n                \"role\": \"Editor\",\n                \"ext\": \"erbsql\"\n            },\n            {\n                \"name\": \"Ruby source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"rb\",\n                    \"rbx\",\n                    \"rjs\",\n                    \"rxml\"\n                ]\n            },\n            {\n                \"name\": \"Sass source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"sass\",\n                    \"scss\"\n                ]\n            },\n            {\n                \"name\": \"Scheme source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"scm\",\n                    \"sch\"\n                ]\n            },\n            {\n                \"name\": \"Setext document\",\n                \"role\": \"Editor\",\n                \"ext\": \"ext\"\n            },\n            {\n                \"name\": \"Shell script\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"sh\",\n                    \"ss\",\n                    \"bashrc\",\n                    \"bash_profile\",\n                    \"bash_login\",\n                    \"profile\",\n                    \"bash_logout\"\n                ]\n            },\n            {\n                \"name\": \"Slate source\",\n                \"role\": \"Editor\",\n                \"ext\": \"slate\"\n            },\n            {\n                \"name\": \"SQL source\",\n                \"role\": \"Editor\",\n                \"ext\": \"sql\"\n            },\n            {\n                \"name\": \"Standard ML source\",\n                \"role\": \"Editor\",\n                \"ext\": \"sml\"\n            },\n            {\n                \"name\": \"Strings document\",\n                \"role\": \"Editor\",\n                \"ext\": \"strings\"\n            },\n            {\n                \"name\": \"Scalable vector graphics\",\n                \"role\": \"Editor\",\n                \"ext\": \"svg\"\n            },\n            {\n                \"name\": \"SWIG source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"i\",\n                    \"swg\"\n                ]\n            },\n            {\n                \"name\": \"Tcl source\",\n                \"role\": \"Editor\",\n                \"ext\": \"tcl\"\n            },\n            {\n                \"name\": \"TeX document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"tex\",\n                    \"sty\",\n                    \"cls\"\n                ]\n            },\n            {\n                \"name\": \"Plain text document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"text\",\n                    \"txt\",\n                    \"utf8\"\n                ]\n            },\n            {\n                \"name\": \"Textile document\",\n                \"role\": \"Editor\",\n                \"ext\": \"textile\"\n            },\n            {\n                \"name\": \"TOML file\",\n                \"role\": \"Editor\",\n                \"ext\": \"toml\"\n            },\n            {\n                \"name\": \"XHTML document\",\n                \"role\": \"Editor\",\n                \"ext\": \"xhtml\"\n            },\n            {\n                \"name\": \"XML document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"xml\",\n                    \"xsd\",\n                    \"xib\",\n                    \"rss\",\n                    \"tld\",\n                    \"pt\",\n                    \"cpt\",\n                    \"dtml\"\n                ]\n            },\n            {\n                \"name\": \"XSL stylesheet\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"xsl\",\n                    \"xslt\"\n                ]\n            },\n            {\n                \"name\": \"Electronic business card\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"vcf\",\n                    \"vcard\"\n                ]\n            },\n            {\n                \"name\": \"Visual Basic source\",\n                \"role\": \"Editor\",\n                \"ext\": \"vb\"\n            },\n            {\n                \"name\": \"YAML document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"yaml\",\n                    \"yml\"\n                ]\n            },\n            {\n                \"name\": \"Text document\",\n                \"role\": \"Editor\",\n                \"ext\": \"nfo\"\n            },\n            {\n                \"name\": \"Source\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"g\",\n                    \"vss\",\n                    \"d\",\n                    \"e\",\n                    \"gri\",\n                    \"inf\",\n                    \"mel\",\n                    \"build\",\n                    \"re\",\n                    \"textmate\",\n                    \"fxscript\",\n                    \"lgt\"\n                ]\n            },\n            {\n                \"name\": \"Document\",\n                \"role\": \"Editor\",\n                \"ext\": [\n                    \"cfm\",\n                    \"cfml\",\n                    \"dbm\",\n                    \"dbml\",\n                    \"dist\",\n                    \"dot\",\n                    \"ics\",\n                    \"ifb\",\n                    \"dwt\",\n                    \"g\",\n                    \"in\",\n                    \"l\",\n                    \"m4\",\n                    \"mp\",\n                    \"mtml\",\n                    \"orig\",\n                    \"pde\",\n                    \"rej\",\n                    \"servlet\",\n                    \"s5\",\n                    \"tmp\",\n                    \"tpl\",\n                    \"tt\",\n                    \"xql\",\n                    \"yy\",\n                    \"*\"\n                ]\n            }\n        ]\n    },\n    \"scripts\": {\n        \"precommit\": \"pretty-quick --staged\",\n        \"prepush\": \"yarn run build && yarn run lint\",\n        \"build\": \"yarn run build:browser && yarn run build:webview_preload && yarn run build:main && yarn run build:plugins && yarn run build:cli\",\n        \"build-debug\": \"yarn run build:browser-debug && yarn run build:main && yarn run build:plugins\",\n        \"build:browser\": \"webpack --config browser/webpack.production.config.js\",\n        \"build:browser-debug\": \"webpack --config browser/webpack.debug.config.js\",\n        \"build:main\": \"cd main && tsc -p tsconfig.json\",\n        \"build:plugins\": \"run-p build:plugin:*\",\n        \"build:cli\": \"cd cli && tsc -p tsconfig.json\",\n        \"build:plugin:oni-plugin-typescript\": \"cd vim/core/oni-plugin-typescript && yarn run build\",\n        \"build:plugin:oni-plugin-git\": \"cd vim/core/oni-plugin-git && yarn run build\",\n        \"build:plugin:oni-plugin-markdown-preview\": \"cd extensions/oni-plugin-markdown-preview && yarn run build\",\n        \"build:plugin:oni-plugin-quickopen\": \"cd extensions/oni-plugin-quickopen && yarn run build\",\n        \"build:test\": \"yarn run build:test:unit && yarn run build:test:integration\",\n        \"build:test:integration\": \"cd test && tsc -p tsconfig.json\",\n        \"build:test:unit\": \"run-s build:test:unit:*\",\n        \"build:test:unit:browser\": \"rimraf lib_test/browser && cd browser && tsc -p tsconfig.test.json\",\n        \"build:test:unit:main\": \"rimraf lib_test/main && cd main && tsc -p tsconfig.test.json\",\n        \"build:webview_preload\": \"cd webview_preload && tsc -p tsconfig.json\",\n        \"check-cached-binaries\": \"node build/script/CheckBinariesForBuild.js\",\n        \"copy-icons\": \"node build/CopyIcons.js\",\n        \"debug:test:unit:browser\": \"cd browser && tsc -p tsconfig.test.json && electron-mocha --interactive --debug --renderer --require testHelpers.js --recursive ../lib_test/browser/test\",\n        \"demo:screenshot\": \"yarn run build:test && cross-env DEMO_TEST=HeroScreenshot mocha -t 30000000 lib_test/test/Demo.js\",\n        \"demo:video\": \"yarn run build:test && cross-env DEMO_TEST=HeroDemo mocha -t 30000000 lib_test/test/Demo.js\",\n        \"dist:win:x86\": \"cross-env ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES=1 build --arch ia32 --publish never\",\n        \"dist:win:x64\": \"cross-env ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES=1 build --arch x64 --publish never\",\n        \"pack:win\": \"node build/BuildSetupTemplate.js && innosetup-compiler dist/setup.iss --verbose --O=dist\",\n        \"test\": \"yarn run test:unit && yarn run test:integration\",\n        \"test:setup\": \"yarn run build:test:integration && mocha -t 120000 --recursive lib_test/test/setup\",\n        \"test:integration\": \"yarn run build:test:integration && mocha -t 120000 lib_test/test/CiTests.js --bail\",\n        \"test:unit:react\": \"jest --config ./jest.config.js ./ui-tests\",\n        \"test:unit:react:watch\": \"jest --config ./jest.config.js ./ui-tests --watch\",\n        \"test:unit:react:coverage\": \"jest --config ./jest.config.js ./ui-tests --coverage\",\n        \"test:unit:browser\": \"yarn run build:test:unit:browser && cd browser && electron-mocha --renderer --require testHelpers.js --recursive ../lib_test/browser/test\",\n        \"test:unit\": \"yarn run test:unit:browser && yarn run test:unit:main && yarn run test:unit:react\",\n        \"test:unit:main\": \"yarn run build:test:unit:main && cd main && electron-mocha --renderer --recursive ../lib_test/main/test\",\n        \"upload:dist\": \"node build/script/UploadDistributionBuildsToAzure\",\n        \"fix-lint\": \"run-p fix-lint:*\",\n        \"fix-lint:browser\": \"tslint --fix --project browser/tsconfig.json --exclude **/node_modules/**/* --config tslint.json && tslint --fix --project vim/core/oni-plugin-typescript/tsconfig.json --config tslint.json && tslint --fix --project extensions/oni-plugin-markdown-preview/tsconfig.json --config tslint.json\",\n        \"fix-lint:cli\": \"tslint --fix --project cli/tsconfig.json --config tslint.json\",\n        \"fix-lint:main\": \"tslint --fix --project main/tsconfig.json --config tslint.json\",\n        \"fix-lint:test\": \"tslint --fix --project test/tsconfig.json --config tslint.json\",\n        \"lint\": \"yarn run lint:browser && yarn run lint:main && yarn run lint:test\",\n        \"lint:browser\": \"tslint --project browser/tsconfig.json --config tslint.json && tslint --project vim/core/oni-plugin-typescript/tsconfig.json --config tslint.json && tslint --project extensions/oni-plugin-markdown-preview/tsconfig.json --config tslint.json\",\n        \"lint:cli\": \"tslint --project cli/tsconfig.json --config tslint.json\",\n        \"lint:main\": \"tslint --project main/tsconfig.json --config tslint.json\",\n        \"lint:test\": \"tslint --project test/tsconfig.json --config tslint.json && tslint vim/core/oni-plugin-typescript/src/**/*.ts && tslint extensions/oni-plugin-markdown-preview/src/**/*.ts\",\n        \"pack\": \"cross-env ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES=1 build --publish never\",\n        \"ccov:instrument\": \"nyc instrument --all true --sourceMap false lib_test/browser/src lib_test/browser/src_ccov\",\n        \"ccov:test:browser\": \"cross-env ONI_CCOV=1 electron-mocha --renderer --require browser/testHelpers.js -R browser/testCoverageReporter --recursive lib_test/browser/test\",\n        \"ccov:remap:browser:html\": \"cd lib_test/browser/src && remap-istanbul --input ../../../coverage/coverage-final.json --output html-report --type html\",\n        \"ccov:remap:browser:lcov\": \"cd lib_test/browser/src && remap-istanbul --input ../../../coverage/coverage-final.json --output lcov.info --type lcovonly\",\n        \"ccov:clean\": \"rimraf coverage\",\n        \"ccov:upload:jest\": \"cd ./coverage/jest && codecov\",\n        \"ccov:upload\": \"codecov\",\n        \"launch\": \"electron lib/main/src/main.js\",\n        \"start\": \"concurrently --kill-others \\\"yarn run start-hot\\\" \\\"yarn run watch:browser\\\" \\\"yarn run watch:plugins\\\"\",\n        \"start-hot\": \"cross-env ONI_WEBPACK_LOAD=1 NODE_ENV=development electron lib/main/src/main.js\",\n        \"start-not-dev\": \"cross-env electron main.js\",\n        \"watch:browser\": \"webpack-dev-server --config browser/webpack.development.config.js --host localhost --port 8191\",\n        \"watch:plugins\": \"run-p --race watch:plugins:*\",\n        \"watch:plugins:oni-plugin-typescript\": \"cd vim/core/oni-plugin-typescript && tsc --watch\",\n        \"watch:plugins:oni-plugin-markdown-preview\": \"cd extensions/oni-plugin-markdown-preview && tsc --watch\",\n        \"watch:plugins:oni-plugin-git\": \"cd vim/core/oni-plugin-git && tsc --watch\",\n        \"watch:plugins:oni-plugin-quickopen\": \"cd extensions/oni-plugin-quickopen && tsc --watch\",\n        \"install:plugins\": \"run-s install:plugins:*\",\n        \"install:plugins:oni-plugin-markdown-preview\": \"cd extensions/oni-plugin-markdown-preview && yarn install --prod\",\n        \"install:plugins:oni-plugin-prettier\": \"cd extensions/oni-plugin-prettier && yarn install --prod\",\n        \"install:plugins:oni-plugin-git\": \"cd vim/core/oni-plugin-git && yarn install --prod\",\n        \"postinstall\": \"yarn run install:plugins && electron-rebuild && opencollective postinstall\",\n        \"profile:webpack\": \"webpack --config browser/webpack.production.config.js --profile --json > stats.json && webpack-bundle-analyzer browser/stats.json\"\n    },\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/bryphe/oni\"\n    },\n    \"license\": \"MIT\",\n    \"dependencies\": {\n        \"@githubprimer/octicons-react\": \"^8.1.0\",\n        \"chokidar\": \"^2.0.3\",\n        \"color-normalize\": \"^1.0.3\",\n        \"dompurify\": \"^1.0.3\",\n        \"electron-settings\": \"^3.1.4\",\n        \"find-up\": \"2.1.0\",\n        \"font-manager\": \"^0.3.0\",\n        \"fs-extra\": \"^5.0.0\",\n        \"highlight.js\": \"^9.12.0\",\n        \"json5\": \"^1.0.1\",\n        \"keyboard-layout\": \"^2.0.13\",\n        \"marked\": \"^0.4.0\",\n        \"minimist\": \"1.2.0\",\n        \"msgpack-lite\": \"0.1.26\",\n        \"ocaml-language-server\": \"^1.0.27\",\n        \"oni-api\": \"0.0.49\",\n        \"oni-fontkit\": \"^0.0.5\",\n        \"oni-neovim-binaries\": \"0.1.3\",\n        \"oni-ripgrep\": \"0.0.4\",\n        \"oni-types\": \"^0.0.8\",\n        \"react\": \"^16.3.2\",\n        \"react-dnd\": \"^2.5.4\",\n        \"react-dnd-html5-backend\": \"^2.5.4\",\n        \"react-dom\": \"^16.3.2\",\n        \"redux-batched-subscribe\": \"^0.1.6\",\n        \"shell-env\": \"^2.1.0\",\n        \"shelljs\": \"0.7.7\",\n        \"simple-git\": \"^1.92.0\",\n        \"styled-components\": \"^3.4.4\",\n        \"typescript\": \"^3.1.1\",\n        \"vscode-css-languageserver-bin\": \"^1.2.1\",\n        \"vscode-html-languageserver-bin\": \"^1.1.0\",\n        \"vscode-jsonrpc\": \"3.5.0\",\n        \"vscode-languageserver\": \"3.5.0\",\n        \"vscode-languageserver-types\": \"3.13.0\",\n        \"vscode-textmate\": \"3.2.0\"\n    },\n    \"devDependencies\": {\n        \"@types/chokidar\": \"^1.7.5\",\n        \"@types/color\": \"2.0.0\",\n        \"@types/detect-indent\": \"^5.0.0\",\n        \"@types/dompurify\": \"^0.0.31\",\n        \"@types/electron-settings\": \"^3.1.1\",\n        \"@types/enzyme\": \"^3.1.8\",\n        \"@types/fs-extra\": \"^5.0.2\",\n        \"@types/highlight.js\": \"^9.12.2\",\n        \"@types/jest\": \"^23.3.1\",\n        \"@types/jsdom\": \"11.0.0\",\n        \"@types/json5\": \"^0.0.29\",\n        \"@types/lodash\": \"4.14.38\",\n        \"@types/lolex\": \"2.1.0\",\n        \"@types/marked\": \"^0.4.0\",\n        \"@types/minimatch\": \"3.0.1\",\n        \"@types/minimist\": \"1.1.29\",\n        \"@types/mkdirp\": \"0.3.29\",\n        \"@types/mocha\": \"2.2.33\",\n        \"@types/msgpack-lite\": \"0.1.4\",\n        \"@types/node\": \"8.0.53\",\n        \"@types/react\": \"^16.3.16\",\n        \"@types/react-dnd\": \"^2.0.34\",\n        \"@types/react-dnd-html5-backend\": \"^2.1.8\",\n        \"@types/react-dom\": \"^16.0.5\",\n        \"@types/react-motion\": \"0.0.23\",\n        \"@types/react-redux\": \"5.0.12\",\n        \"@types/react-test-renderer\": \"^16.0.0\",\n        \"@types/react-transition-group\": \"^2.0.11\",\n        \"@types/react-virtualized\": \"^9.18.3\",\n        \"@types/redux-batched-subscribe\": \"^0.1.2\",\n        \"@types/redux-mock-store\": \"^1.0.0\",\n        \"@types/rimraf\": \"^2.0.2\",\n        \"@types/shelljs\": \"^0.7.7\",\n        \"@types/sinon\": \"5.0.5\",\n        \"@types/webgl2\": \"^0.0.3\",\n        \"autoprefixer\": \"6.4.0\",\n        \"aws-sdk\": \"^2.202.0\",\n        \"azure-storage\": \"^2.8.1\",\n        \"babel-minify-webpack-plugin\": \"^0.3.1\",\n        \"babel-plugin-dynamic-import-node\": \"^1.2.0\",\n        \"codecov\": \"^3.0.0\",\n        \"color\": \"2.0.0\",\n        \"concurrently\": \"3.1.0\",\n        \"cross-env\": \"3.1.3\",\n        \"css-loader\": \"0.28.4\",\n        \"detect-indent\": \"^5.0.0\",\n        \"electron\": \"2.0.8\",\n        \"electron-builder\": \"^20.5.1\",\n        \"electron-devtools-installer\": \"^2.2.4\",\n        \"electron-mocha\": \"5.0.0\",\n        \"electron-rebuild\": \"^1.7.3\",\n        \"enzyme\": \"^3.3.0\",\n        \"enzyme-adapter-react-16\": \"^1.1.1\",\n        \"enzyme-to-json\": \"^3.3.1\",\n        \"extract-zip\": \"1.6.0\",\n        \"find-process\": \"^1.1.0\",\n        \"fuse.js\": \"2.6.2\",\n        \"github-releases\": \"^0.4.1\",\n        \"html-loader\": \"^0.5.5\",\n        \"husky\": \"^0.14.3\",\n        \"innosetup-compiler\": \"5.5.9\",\n        \"istanbul-api\": \"^1.2.1\",\n        \"istanbul-lib-coverage\": \"^1.1.1\",\n        \"jest\": \"^23.5.0\",\n        \"jest-styled-components\": \"^6.1.1\",\n        \"jsdom\": \"11.0.0\",\n        \"less\": \"2.7.1\",\n        \"less-loader\": \"^4.1.0\",\n        \"less-plugin-autoprefix\": \"1.5.1\",\n        \"lodash\": \"4.17.0\",\n        \"lolex\": \"2.3.1\",\n        \"memory-fs\": \"^0.4.1\",\n        \"minimatch\": \"3.0.4\",\n        \"mkdirp\": \"0.5.1\",\n        \"mocha\": \"3.1.2\",\n        \"node-abi\": \"^2.4.1\",\n        \"npm-run-all\": \"^4.1.3\",\n        \"nyc\": \"^11.4.1\",\n        \"oni-core-logging\": \"^1.0.0\",\n        \"oni-release-downloader\": \"^0.0.10\",\n        \"opencollective\": \"1.0.3\",\n        \"prettier\": \"^1.12.1\",\n        \"pretty-quick\": \"^1.5.0\",\n        \"react-hot-loader\": \"^4.0.1\",\n        \"react-motion\": \"0.5.2\",\n        \"react-redux\": \"5.0.6\",\n        \"react-test-renderer\": \"^16.2.0\",\n        \"react-transition-group\": \"2.2.1\",\n        \"react-virtualized\": \"^9.19.1\",\n        \"redux\": \"3.7.2\",\n        \"redux-mock-store\": \"^1.5.3\",\n        \"redux-observable\": \"0.17.0\",\n        \"redux-thunk\": \"2.2.0\",\n        \"remap-istanbul\": \"^0.10.1\",\n        \"reselect\": \"3.0.1\",\n        \"rxjs\": \"5.5.8\",\n        \"sinon\": \"5.0.5\",\n        \"spectron\": \"^3.8.0\",\n        \"style-loader\": \"0.18.2\",\n        \"sudo-prompt\": \"7.1.1\",\n        \"ts-jest\": \"^23.0.0\",\n        \"ts-loader\": \"^4.2.0\",\n        \"tslint\": \"^5.11.0\",\n        \"typescript-plugin-styled-components\": \"^0.0.6\",\n        \"vscode-snippet-parser\": \"0.0.5\",\n        \"wcwidth\": \"1.0.1\",\n        \"webdriverio\": \"4.8.0\",\n        \"webpack\": \"^4.6.0\",\n        \"webpack-bundle-analyzer\": \"^2.11.1\",\n        \"webpack-cli\": \"^2.0.14\",\n        \"webpack-dev-server\": \"^3.1.3\"\n    },\n    \"collective\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/oni\",\n        \"logo\": \"https://opencollective.com/opencollective/logo.txt\"\n    }\n}\n"
  },
  {
    "path": "preload.js",
    "content": "if (!process.env.ONI_WEBPACK_LOAD) {\n    window.eval = global.eval = () => console.warn(\"eval is not available\")\n}\n\nconsole.timeStamp(\"browser.domloaded\")\nvar path = \"lib/browser/bundle.js\"\nif (process.env.ONI_WEBPACK_LOAD) {\n    path = \"scripts/dev_webpack_loader.js\"\n}\nvar scriptTag = document.createElement(\"script\")\nscriptTag.src = path\ndocument.body.appendChild(scriptTag)\n"
  },
  {
    "path": "scripts/dev_webpack_loader.js",
    "content": "// Helper script to load webpack\n\nconst WEBPACK_BUNDLE_URL = \"http://localhost:8191/bundle.js\"\n\nconst hotReloadElement = document.createElement(\"div\")\nhotReloadElement.style.position = \"absolute\"\nhotReloadElement.style.left = \"0px\"\nhotReloadElement.style.right = \"0px\"\nhotReloadElement.style.bottom = \"0px\"\nhotReloadElement.style.top = \"0px\"\nhotReloadElement.style.display = \"flex\"\nhotReloadElement.style.backgroundColor = \"black\"\nhotReloadElement.style.color = \"white\"\nhotReloadElement.style.flexDirection = \"column\"\nhotReloadElement.style.justifyContent = \"center\"\nhotReloadElement.style.alignItems = \"center\"\n\nconst oniImage = document.createElement(\"img\")\noniImage.className = \"webpack-loading-image\"\noniImage.src = \"build/icons/128x128.png\"\n\nconst textElement = document.createElement(\"span\")\ntextElement.className = \"webpack-loading-text\"\ntextElement.textContent = \"BUILD: Waiting for webpack initialization...\"\n\nconst statusElement = document.createElement(\"span\")\nstatusElement.className = \"webpack-loading-status\"\nstatusElement.textContent = \"\"\n\nhotReloadElement.appendChild(oniImage)\nhotReloadElement.appendChild(textElement)\nhotReloadElement.appendChild(statusElement)\n\ndocument.body.appendChild(hotReloadElement)\n\nlet attempt = 1\n\nlet initialized = false\n\nconst setStatus = statusText => {\n    console.log(statusText)\n    statusElement.textContent = statusText\n}\n\nconst check = () => {\n    setStatus(\n        \"Checking bundle - attempt \" +\n            attempt.toString() +\n            \". Check console where you ran `npm run start` for output / status...\",\n    )\n\n    fetch(WEBPACK_BUNDLE_URL).then(\n        () => {\n            setStatus(\"Webpack initialized! Loading...\")\n            start()\n        },\n        () => {\n            setStatus(\"Last fetch failed. Retrying...\")\n        },\n    )\n}\ncheck()\n\nlet interval = window.setInterval(() => {\n    check()\n    attempt++\n}, 1000)\n\nconst start = () => {\n    if (!initialized) {\n        initialized = true\n        window.clearInterval(interval)\n\n        document.body.removeChild(hotReloadElement)\n\n        const scriptTag = document.createElement(\"script\")\n        scriptTag.src = WEBPACK_BUNDLE_URL\n        document.body.appendChild(scriptTag)\n\n        // Once the script comes in, it likely will have missed the 'init' event\n        scriptTag.onload = () => {\n            require(\"electron\")\n                .remote.getCurrentWindow()\n                .send(\"init\", { args: [], workingDirectory: process.cwd() })\n        }\n    }\n}\n"
  },
  {
    "path": "scripts/webm2gif.sh",
    "content": "#!/bin/bash\n# This script uses `ffmpeg` to convert a .webm file\n# (specified by the first argument) to an animated gif\n\necho The argument is \"$1\" \"$2\"\n\nffmpeg -y -i \"$1\" -vf fps=10,scale=0:0:flags=lanczos,palettegen palette.png\n\nffmpeg -i \"$1\" -i palette.png -filter_complex \"fps=10,scale=0:0:flags=lanczos[x];[x][1:v]paletteuse\" output.gif\n"
  },
  {
    "path": "test/CiTests.ts",
    "content": "import * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\n\nimport { IFailedTest, Oni, runInProcTest } from \"./common\"\n\nconst LongTimeout = 5000\n\nconst CiTests = [\n    // Core functionality tests\n    \"Api.Buffer.AddLayer\",\n    \"Api.Overlays.AddRemoveTest\",\n    \"AutoClosingPairsTest\",\n    \"AutoCompletionTest-CSS\",\n    \"AutoCompletionTest-HTML\",\n    \"AutoCompletionTest-TypeScript\",\n\n    \"Browser.LocationTest\",\n\n    \"Configuration.JavaScriptEditorTest\",\n    \"Configuration.TypeScriptEditor.NewConfigurationTest\",\n    \"Configuration.TypeScriptEditor.CompletionTest\",\n\n    \"Welcome.BufferLayerTest\",\n\n    \"TabBarSneakTest\",\n    \"initVimPromptNotificationTest\",\n    \"Editor.BuffersCursorTest\",\n    \"Editor.ExternalCommandLineTest\",\n    \"Editor.BufferModifiedState\",\n    \"Editor.OpenFile.PathWithSpacesTest\",\n    \"Editor.ScrollEventTest\",\n    \"Editor.TabModifiedState\",\n    \"Editor.CloseTabWithTabModesTabsTest\",\n    \"Editor.NextPreviousErrorTest\",\n    \"Explorer.LocateBufferTest\",\n    \"MarkdownPreviewTest\",\n    \"PrettierPluginTest\",\n    \"PaintPerformanceTest\",\n    \"QuickOpenTest\",\n    \"StatusBar-Mode\",\n    \"Neovim.InvalidInitVimHandlingTest\",\n    \"Neovim.CallOniCommands\",\n    \"NoInstalledNeovim\",\n    \"Sidebar.ToggleSplitTest\",\n    \"LargePasteTest\",\n\n    \"Snippets.BasicInsertTest\",\n\n    \"WindowManager.ErrorBoundary\",\n    \"Workspace.ConfigurationTest\",\n    // Regression Tests\n    \"Regression.1251.NoAdditionalProcessesOnStartup\",\n    \"Regression.1296.SettingColorsTest\",\n    \"Regression.1295.UnfocusedWindowTest\",\n    \"Regression.1799.MacroApplicationTest\",\n    \"Regression.2047.VerifyCanvasIsIntegerSize\",\n\n    \"TextmateHighlighting.DebugScopesTest\",\n    \"TextmateHighlighting.ScopesOnEnterTest\",\n    \"TextmateHighlighting.TokenColorOverrideTest\",\n    \"IndentGuide.BufferLayerTest\",\n    \"ColorHighlight.BufferLayerTest\",\n\n    \"Theming.LightAndDarkColorsTest\",\n\n    // This test occasionally hangs and breaks tests after - trying to move it later...\n    \"LargeFileTest\",\n]\n\nconst WindowsOnlyTests = [\n    // TODO: Stabilize this test on OSX / Linux, too!\n    \"Regression.1819.AutoReadCheckTimeTest\",\n]\n\nconst OSXOnlyTests = [\"OSX.WindowTitleTest\"]\n\n// tslint:disable:no-console\n\nimport * as Platform from \"./../browser/src/Platform\"\n\nexport interface ITestCase {\n    name: string\n    testPath: string\n    configPath: string\n}\n\nconst FGRED = \"\\x1b[31m\"\nconst FGWHITE = \"\\x1b[37m\"\nconst FGGREEN = \"\\x1b[32m\"\nconst FGYELLOW = \"\\x1b[33m\"\n\n// tslint:disable-next-line only-arrow-functions\ndescribe(\"ci tests\", function() {\n    const tests = Platform.isWindows()\n        ? [...CiTests, ...WindowsOnlyTests]\n        : Platform.isMac()\n            ? [...CiTests, ...OSXOnlyTests]\n            : CiTests\n\n    const testFailures: IFailedTest[] = []\n    tests.forEach(test => {\n        runInProcTest(path.join(__dirname, \"ci\"), test, 5000, testFailures)\n    })\n\n    // After all of the tests are completed display failures\n    after(() => {\n        if (testFailures.length > 0) {\n            console.log(\"\\n\", FGRED, \"---- FAILED TESTS ----\\n\")\n            testFailures.forEach(failure => {\n                console.log(FGYELLOW, \"  [FAILED]:\", FGWHITE, failure.test)\n                console.log(FGWHITE, \"     Expected:\", FGGREEN, failure.expected)\n                console.log(FGWHITE, \"     Actual:\", FGRED, failure.actual)\n                console.log(FGWHITE, \"     Path:\", failure.path, \"\\n\")\n                // TODO: Add line number\n            })\n            console.log(\"\")\n        }\n    })\n})\n"
  },
  {
    "path": "test/Demo.ts",
    "content": "import * as assert from \"assert\"\nimport * as path from \"path\"\n\nimport { runInProcTest } from \"./common\"\n\nconst TestToRun = process.env[\"DEMO_TEST\"] // tslint:disable-line\n\n// tslint:disable:no-console\n\nconsole.log(\"Running test: \" + TestToRun)\n\ndescribe(\"demo tests\", () => {\n    runInProcTest(path.join(__dirname, \"demo\"), TestToRun, 50000)\n})\n"
  },
  {
    "path": "test/Manual.md",
    "content": "# Manual Test Cases\n\nIdeally, these test cases could be automated to minimize overhead with the release process\n\n## Internationalization\n\n- German:\n    - [, ] (Alt5,6 on German OSX, Alt7/8 on Windows International)\n    - {} (Alt 8,9 on German OSX, Alt 6,9 on Windows International)\n    - öÖ (: english keyboard)\n    - üÜ ([ english keyboard)\n- Hiragana: \n    - Oni (鬼)\n    - tekisuto (テキスト)\n- English International: \n    - `a (`+a)\n    - 'a ('+a)\n    - ß (AltGr+S)\n    - Dead key in normal mode - navigate to mark (ma, `+space+a)\n    - Dead key on command line\n- Spanish:\n    - [ Left bracket (AltGr+[ on Windows es-ES)\n"
  },
  {
    "path": "test/ci/Api.Buffer.AddLayer.tsx",
    "content": "/**\n * Test script for the Oni Layers API, tests the adding of new files and splits.\n */\n\nimport * as React from \"react\"\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nexport class TestLayer implements Oni.BufferLayer {\n    public get id(): string {\n        return \"automation.test.layer\"\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        let className = \"test-automation-layer \"\n\n        if (context.isActive) {\n            className += \"active\"\n        } else {\n            className += \"inactive\"\n        }\n\n        return <div className={className}>{context.visibleLines.join(os.EOL)}</div>\n    }\n}\n\nconst getLayerElements = () => {\n    return document.querySelectorAll(\".test-automation-layer\")\n}\n\nconst getActiveLayerElements = () => {\n    return document.querySelectorAll(\".test-automation-layer.active\")\n}\n\nconst getInactiveLayerElements = () => {\n    return document.querySelectorAll(\".test-automation-layer.inactive\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni, \"line1\\nline2\")\n\n    oni.editors.activeEditor.activeBuffer.addLayer(new TestLayer())\n\n    // Wait for layer to appear\n    await oni.automation.waitFor(() => getLayerElements().length === 1)\n\n    // Validate the buffer layer has rendered the 'visibleLines'\n    const element = getLayerElements()[0]\n    assert.ok(element.textContent.indexOf(\"line1\") >= 0, \"Validate line1 is present in the layer\")\n    assert.ok(element.textContent.indexOf(\"line2\") >= 0, \"Validate line2 is present in the layer\")\n\n    // Validate elements\n    assert.strictEqual(getActiveLayerElements().length, 1)\n    assert.strictEqual(getInactiveLayerElements().length, 0)\n\n    oni.automation.sendKeys(\":vsp<CR>\")\n\n    await oni.automation.waitFor(() => getLayerElements().length === 2)\n\n    assert.strictEqual(getActiveLayerElements().length, 1)\n    assert.strictEqual(getInactiveLayerElements().length, 1)\n}\n"
  },
  {
    "path": "test/ci/Api.Overlays.AddRemoveTest.tsx",
    "content": "/**\n * Test script for the Oni Overlays API, tests the Show / Hide functions.\n */\n\nimport * as React from \"react\"\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nconst getOverlayElements = () => {\n    return document.querySelectorAll(\".test-automation-overlay\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni)\n\n    const oniAsAny: any = oni\n\n    const overlays = oniAsAny.overlays\n\n    const overlay = overlays.createItem()\n    overlay.setContents(<div className=\"test-automation-overlay\" />)\n    overlay.show()\n\n    // Wait for overlay to appear\n    await oni.automation.waitFor(() => getOverlayElements().length === 1)\n\n    overlay.hide()\n\n    // Wait for overlay to disappear\n    await oni.automation.waitFor(() => getOverlayElements().length === 0)\n}\n"
  },
  {
    "path": "test/ci/Assert.ts",
    "content": "/**\n * An assertion framework\n */\n\nimport * as stock_assert from \"assert\"\n\nexport class Assertor {\n    private _lastSuccessIndex: number = 0\n\n    constructor(private _testName: string, private _oni: any = null) {}\n\n    public contains(containing: string, contained: string, name: string): void {\n        this.assert(\n            containing.indexOf(contained) >= 0,\n            `${name} expected to contain \\`${contained}\\`, but instead has only \\`${containing}\\``,\n        )\n    }\n\n    public isEmpty(str: string, name: string): void {\n        this.assert(\n            str.length === 0,\n            `${name} expected to be empty, instead it has \\`${str}\\` (${str.length} characters)`,\n        )\n    }\n\n    public async waitFor(\n        getData: () => any,\n        action: (data: any) => boolean,\n        timeout: number = 10000,\n    ) {\n        const SLEEP_TIME = 50\n        let slept = 0\n        do {\n            await this._oni.automation.sleep(SLEEP_TIME)\n            slept += SLEEP_TIME\n        } while (slept < timeout && !action(getData()))\n\n        const data = getData()\n        this.assert(action(data), `timed out with \"${data}\" after ${slept}ms`)\n    }\n\n    public defined(obj: any, name: string): void {\n        if (obj === null) {\n            this.failed(`${name} is null`)\n        } else if (obj === undefined) {\n            this.failed(`${name} is undefined`)\n        } else {\n            this._lastSuccessIndex += 1\n        }\n    }\n\n    public equal(o1: any, o2: any): void {\n        if (o1 === o2) {\n            this._lastSuccessIndex += 1\n        } else {\n            this.failed(`${o1} !== ${o2}`)\n        }\n    }\n\n    /**\n     * A temporary solution that works around the issue that assert doesn't print the error\n     */\n    public assert(condition: boolean, message: string): void {\n        if (condition) {\n            this._lastSuccessIndex += 1\n        } else {\n            this.failed(message)\n        }\n    }\n\n    private failed(message: string): void {\n        const index = this._lastSuccessIndex + 1\n        const messagePrefix = `[${this._testName}] Assertion #${index}: `\n        console.error(messagePrefix + message) // tslint:disable-line no-console\n        stock_assert(false, message)\n    }\n}\n"
  },
  {
    "path": "test/ci/AutoClosingPairsTest.ts",
    "content": "/**\n * Test script to verify the behaviour of the auto closing pair feature.\n *\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nconst delay = 0\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni)\n\n    // Wait for the '{' binding to show up, so we get\n    // a deterministic result.\n    await oni.automation.waitFor(() => oni.input.hasBinding(\"(\"))\n    await oni.automation.waitFor(() => oni.input.hasBinding(\")\"))\n\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n\n    oni.automation.sendKeys(\"const test = \")\n    oni.automation.sendKeys(\"{\")\n    oni.automation.sendKeys(\"<enter>\")\n    oni.automation.sendKeys(\"window.setTimeout\")\n    oni.automation.sendKeys(\"(\")\n    oni.automation.sendKeys(\"(\")\n    oni.automation.sendKeys(\")\")\n    oni.automation.sendKeys(\" => \")\n    oni.automation.sendKeys(\"{\")\n    oni.automation.sendKeys(\"<enter>\")\n    oni.automation.sendKeys(\"let testString = \")\n    oni.automation.sendKeys('\"')\n    oni.automation.sendKeys(\"Oni\")\n    oni.automation.sendKeys('\"')\n    oni.automation.sendKeys(\"<esc>\")\n\n    // Because the input is asynchronous, we need to use `waitFor` to wait\n    // for them to complete.\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n\n    const lines: string[] = await oni.editors.activeEditor.activeBuffer.getLines(0, 5)\n\n    const expectedResult = [\n        \"const test = {\",\n        \"    window.setTimeout(() => {\",\n        '        let testString = \"Oni\"',\n        \"    })\",\n        \"}\",\n    ]\n\n    assert.deepEqual(lines, expectedResult, \"Verify lines are as expected\")\n}\n\n// Bring in custom config to include the \"\" pair, which isn't part of the default config.\nexport const settings = {\n    config: {\n        \"autoClosingPairs.default\": [\n            { open: \"{\", close: \"}\" },\n            { open: \"[\", close: \"]\" },\n            { open: \"(\", close: \")\" },\n            { open: '\"', close: '\"' },\n        ],\n        \"autoClosingPairs.enabled\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/AutoCompletionTest-CSS.ts",
    "content": "/**\n * Test scripts for Auto Complete for a CSS file.\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getCompletionElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"css\", oni)\n\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.sleep(500)\n    oni.automation.sendKeys(\".test { pos\")\n\n    // Wait for completion popup to show\n    await oni.automation.waitFor(() => getCompletionElement() !== null)\n\n    // Check for 'alert' as an available completion\n    const completionElement = getCompletionElement()\n    const textContent = completionElement.textContent\n\n    assert.ok(\n        textContent.indexOf(\"position\") >= 0,\n        \"Verify 'position' was presented as a completion\",\n    )\n}\n"
  },
  {
    "path": "test/ci/AutoCompletionTest-HTML.ts",
    "content": "/**\n * Test scripts for Auto Complete for a HTML file.\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getCompletionElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"html\", oni)\n\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.sleep(500)\n    oni.automation.sendKeys(\"<lt>body s\")\n\n    // Wait for completion popup to show\n    await oni.automation.waitFor(() => getCompletionElement() !== null)\n\n    // Check for 'alert' as an available completion\n    const completionElement = getCompletionElement()\n    const textContent = completionElement.textContent\n\n    assert.ok(textContent.indexOf(\"style\") >= 0, \"Verify 'style' was presented as a completion\")\n}\n"
  },
  {
    "path": "test/ci/AutoCompletionTest-Reason.ts",
    "content": "/**\n * Test scripts for `ocaml-language-server` completion for Reason\n */\n\nimport * as assert from \"assert\"\nimport * as childProcess from \"child_process\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as rimraf from \"rimraf\"\n\nimport * as Oni from \"oni-api\"\n\nimport { getCompletionElement, navigateToFile } from \"./Common\"\n\n// tslint:disable:no-console\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    const reasonProjectFolder = createReasonProject()\n    const fileToOpen = path.join(reasonProjectFolder, \"src\", \"demo.re\")\n\n    await navigateToFile(fileToOpen, oni)\n\n    oni.automation.sendKeys(\"o\")\n    await oni.automation.sleep(500)\n    oni.automation.sendKeys(\"Js.\")\n\n    // Wait for completion popup to show\n    await oni.automation.waitFor(() => getCompletionElement() !== null)\n\n    // Check for 'alert' as an available completion\n    const completionElement = getCompletionElement()\n    const textContent = completionElement.textContent\n\n    assert.ok(textContent.indexOf(\"log\") >= 0, \"Verify 'log' was presented as a completion\")\n}\n\nconst createReasonProject = (): string => {\n    const nodeModulesBinFolder = path.join(__dirname, \"..\", \"..\", \"..\", \"node_modules\", \".bin\")\n\n    const executable = os.platform() === \"win32\" ? \"bsb.cmd\" : \"bsb\"\n\n    const bsbExecutable = path.join(nodeModulesBinFolder, executable)\n\n    console.log(\"bsb executable: \" + bsbExecutable)\n\n    const projectFolder = path.join(os.tmpdir(), \"oni-test-reason-project\")\n\n    if (fs.existsSync(projectFolder)) {\n        rimraf.sync(projectFolder)\n    }\n\n    console.log(\"Creating project at: \" + projectFolder)\n\n    const output = childProcess.spawnSync(\n        bsbExecutable,\n        [\"-init\", \"oni-test-reason-project\", \"-theme\", \"basic-reason\"],\n        { cwd: os.tmpdir() },\n    )\n    console.log(output.stderr.toString())\n    console.log(output.stdout.toString())\n\n    console.log(\"Building project...\")\n\n    const output2 = childProcess.execSync(\"npm run build\", { cwd: projectFolder })\n\n    console.log(output2.toString())\n\n    console.log(\"Project built successfully!\")\n\n    return projectFolder\n}\n"
  },
  {
    "path": "test/ci/AutoCompletionTest-TypeScript.ts",
    "content": "/**\n * Test scripts for Auto Complete for a Typescript file.\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getCompletionElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"ts\", oni)\n\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.sleep(500)\n    oni.automation.sendKeys(\"window.a\")\n\n    // Wait for completion popup to show\n    await oni.automation.waitFor(() => getCompletionElement() !== null, 120000)\n\n    // Check for 'alert' as an available completion\n    const completionElement = getCompletionElement()\n    const textContent = completionElement.textContent\n\n    assert.ok(textContent.indexOf(\"alert\") >= 0, \"Verify 'alert' was presented as a completion\")\n}\n"
  },
  {
    "path": "test/ci/Browser.LocationTest.ts",
    "content": "/**\n * Test scripts for Auto Complete for a Typescript file.\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { WebviewTag } from \"electron\"\n\nimport { getElementsBySelector } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    const getWebView = (): WebviewTag | null => {\n        const elems = getElementsBySelector(\"webview\")\n        return elems.length > 0 ? elems[0] : null\n    }\n\n    const waitForWebViewUrl = (urlPart: string): boolean => {\n        const webview = getWebView()\n\n        if (!webview) {\n            return false\n        }\n\n        const url = webview.getURL()\n\n        return url.indexOf(urlPart) >= 0\n    }\n\n    oni.commands.executeCommand(\"browser.openUrl.verticalSplit\", \"https://github.com/onivim/oni\")\n\n    await oni.automation.waitFor(() => getWebView() !== null)\n    await oni.automation.waitFor(() => waitForWebViewUrl(\"github.com\"))\n\n    await oni.automation.sendKeys(\"<c-g>\")\n    await oni.automation.sleep(500)\n\n    // We'll sneak to the browser address and load a new site\n    const anyOni = oni as any\n    const sneak = anyOni.sneak.getSneakMatchingTag(\"browser.address\")\n\n    const keys: string = sneak.triggerKeys.toLowerCase()\n    await anyOni.automation.sendKeysV2(keys)\n\n    await oni.automation.sleep(500)\n\n    await anyOni.automation.sendKeysV2(\"https://www.onivim.io\")\n\n    await oni.automation.sleep(500)\n\n    await anyOni.automation.sendKeysV2(\"<CR>\")\n\n    await oni.automation.waitFor(() => waitForWebViewUrl(\"onivim.io\"))\n\n    assert.ok(\n        getWebView()\n            .getURL()\n            .indexOf(\"onivim.io\") >= 0,\n        \"Successfully navigated to onivim.io\",\n    )\n}\n"
  },
  {
    "path": "test/ci/ColorHighlight.BufferLayerTest.ts",
    "content": "/**\n * Test script for the Color highlight Layer.\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\nimport { createNewFile } from \"./Common\"\n\nconst testStr = `\n    .test {\n        background-color: blue;\n        color: red;\n    }\n`\n\nconst getColorHighlights = () => document.querySelectorAll(\"[data-id='color-highlight']\")\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"css\", oni, testStr)\n\n    const elements = getColorHighlights()\n\n    assert.ok(elements.length === 2, \"Validate a color highlight is present in the layer\")\n\n    // Render the same test string in an incompatible buffer and plugin should not render\n    await createNewFile(\"md\", oni, testStr)\n    const markdownIndents = getColorHighlights()\n\n    assert.ok(markdownIndents.length === 0, \"No highlights are rendered in an incompatible file\")\n}\n\nexport const settings = {\n    config: {\n        \"oni.useDefaultConfig\": true,\n        \"oni.loadInitVim\": false,\n        \"experimental.colorHighlight.enabled\": true,\n        \"experimental.colorHighlight.filetypes\": [\".tsx\", \".ts\", \".jsx\", \".js\", \".css\"],\n        \"_internal.hasCheckedInitVim\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/Common.ts",
    "content": "/**\n * Common functions used across the CI tests.\n */\n\nimport * as Oni from \"oni-api\"\n\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nexport const getCompletionElement = () => {\n    return getSingleElementBySelector(\"[data-id='autocompletion']\")\n}\n\ninterface IGetTab {\n    dirty: boolean\n}\n\nexport const getSelectedTabElement = ({ dirty = false }: IGetTab) => {\n    const isDirty = dirty ? \"is-dirty\" : \"not-dirty\"\n    return getSingleElementBySelector(`[data-status='tab-selected-${isDirty}']`)\n}\n\nexport const getAllTabs = () => {\n    return getElementsBySelector(`[data-id='tab']`)\n}\n\nexport const getTabCloseButtonByIndex = (index: number) => {\n    const tabs = getAllTabs()\n    const tab = tabs[index]\n    return tab ? tab.querySelector(\"[data-id='tab-close-button']\") : null\n}\n\nexport const getTabsContainer = () => {\n    return getSingleElementBySelector(`[data-id='tabs']`)\n}\n\nexport const getCollateralPath = () => {\n    return path.join(__dirname, \"..\", \"..\", \"..\", \"test\", \"collateral\")\n}\n\nexport const getElementByClassName = (className: string): HTMLElement => {\n    const elements = document.body.getElementsByClassName(className)\n\n    if (!elements || !elements.length) {\n        return null\n    } else {\n        return elements[0] as HTMLElement\n    }\n}\n\nexport const getElementsBySelector = (selector: string) => {\n    const elements = document.body.querySelectorAll(selector)\n    return elements || []\n}\n\nexport const getSingleElementBySelector = (selector: string) =>\n    document.body.querySelector(selector)\n\nexport const createNewFile = async (\n    fileExtension: string,\n    oni: Oni.Plugin.Api,\n    contents?: string,\n): Promise<void> => {\n    const tempFilePath = getTemporaryFilePath(fileExtension)\n\n    if (contents) {\n        fs.writeFileSync(tempFilePath, contents)\n    }\n\n    await navigateToFile(tempFilePath, oni)\n}\n\nexport const getTemporaryFilePath = (fileExtension: string): string => {\n    const dir = os.tmpdir()\n    const testFileName = `testFile-${new Date().getTime()}.${fileExtension}`\n    return path.join(dir, testFileName)\n}\n\nexport const getTemporaryFolder = (): string => {\n    const dir = os.tmpdir()\n    const testFolderName = `oni-test-folder-${new Date().getTime()}`\n    const testFolderPath = path.join(dir, testFolderName)\n    return testFolderPath\n}\n\nexport const navigateToFile = async (filePath: string, oni: Oni.Plugin.Api): Promise<void> => {\n    oni.automation.sendKeys(\":e \" + filePath)\n    oni.automation.sendKeys(\"<cr>\")\n\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.filePath === filePath,\n        10000,\n    )\n}\n\nexport const waitForCommand = async (command: string, oni: Oni.Plugin.Api): Promise<void> => {\n    return oni.automation.waitFor(() => {\n        const anyCommands = oni.commands as any\n        return anyCommands.hasCommand(command)\n    }, 10000)\n}\n\nexport async function awaitEditorMode(oni: Oni.Plugin.Api, mode: string): Promise<void> {\n    function condition(): boolean {\n        return oni.editors.activeEditor.mode === mode\n    }\n    await oni.automation.waitFor(condition)\n}\n\nexport async function insertText(oni: Oni.Plugin.Api, text: string): Promise<void> {\n    oni.automation.sendKeys(\"i\")\n    await awaitEditorMode(oni, \"insert\")\n    oni.automation.sendKeys(`${text}<ESC>`)\n    await awaitEditorMode(oni, \"normal\")\n}\n\n/**\n * Create temporary workspace with a file `src/File.ts` and return workspace directory\n */\nexport async function useTempWorkspace(oni: Oni.Plugin.Api) {\n    // Create our \"workspace\"\n    const rootPath = getTemporaryFolder()\n    fs.mkdirSync(rootPath)\n    // Create workspace subdir.\n    const directoryPath = path.join(rootPath, \"src\")\n    fs.mkdirSync(directoryPath)\n    // Create workspace file.\n    const filePath = path.join(directoryPath, \"File.ts\")\n    fs.writeFileSync(filePath, \"\")\n    // Switch to workspace.\n    await oni.workspace.changeDirectory(rootPath)\n    return rootPath\n}\n"
  },
  {
    "path": "test/ci/Configuration.JavaScriptEditorTest.ts",
    "content": "/**\n * Test script for the JavaScript Configuration Editor\n *\n * In the case where there is a javascript config file, but no\n * corresponding typescript file, the javascript configuration file\n * should be opened.\n */\n\nimport * as React from \"react\"\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, waitForCommand } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await waitForCommand(\"oni.config.openUserConfig\", oni)\n    oni.commands.executeCommand(\"oni.config.openUserConfig\")\n\n    await oni.automation.waitFor(() => {\n        return oni.editors.activeEditor.activeBuffer.language === \"javascript\"\n    }, 10000)\n\n    await oni.automation.waitFor(() => {\n        return oni.editors.activeEditor.activeBuffer.lineCount > 0\n    })\n\n    const bufferLines = await oni.editors.activeEditor.activeBuffer.getLines(0, 100)\n    const allLines = bufferLines.join()\n\n    // Validate that the configuration was loaded correctly, and it is the javascript configuration\n    assert.ok(allLines.indexOf(\"someTestConfig\") >= 0)\n    assert.strictEqual(oni.editors.activeEditor.activeBuffer.language, \"javascript\")\n}\n\nexport const settings = {\n    config: {\n        someTestConfig: 1,\n    },\n}\n"
  },
  {
    "path": "test/ci/Configuration.TypeScriptEditor.CompletionTest.ts",
    "content": "/**\n * Test script for the TypeScript Configuration Editor\n *\n * Validate that appropriate typings are coming in -\n * in particular, we should be getting typing info\n * for the `oni-api` surface.\n */\n\nimport * as React from \"react\"\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getCompletionElement, getTemporaryFolder, waitForCommand } from \"./Common\"\n\nconst emptyConfigPath = path.join(getTemporaryFolder(), \"config.js\")\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await waitForCommand(\"oni.config.openUserConfig\", oni)\n    oni.commands.executeCommand(\"oni.config.openUserConfig\")\n\n    await oni.automation.waitFor(() => {\n        return oni.editors.activeEditor.activeBuffer.language === \"typescript\"\n    }, 10000)\n\n    await oni.automation.waitFor(() => {\n        return oni.editors.activeEditor.activeBuffer.lineCount > 0\n    })\n\n    // Put cursor after 'activate' line\n    oni.automation.sendKeys(\":7\")\n    oni.automation.sendKeys(\"<cr>\")\n    oni.automation.sendKeys(\"i\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n\n    oni.automation.sendKeys(\"oni.a\")\n\n    const hasCompletionElement = () =>\n        getCompletionElement() && getCompletionElement().textContent.indexOf(\"automation\") >= 0\n\n    await oni.automation.waitFor(hasCompletionElement, 120000)\n\n    assert.ok(hasCompletionElement(), \"Got completion element!\")\n}\n\nexport const settings = {\n    configPath: emptyConfigPath,\n}\n"
  },
  {
    "path": "test/ci/Configuration.TypeScriptEditor.NewConfigurationTest.ts",
    "content": "/**\n * Test script for the TypeScript Configuration Editor\n *\n * In the case where there is no configuration file, a configuration file\n * should be created, and there should be intellisense available for the API\n * surface, and saving should update the configuration file.\n * corresponding typescript file, the javascript configuration file\n * should be opened.\n */\n\nimport * as React from \"react\"\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getTemporaryFolder, waitForCommand } from \"./Common\"\n\nconst emptyConfigPath = path.join(getTemporaryFolder(), \"config.js\")\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await waitForCommand(\"oni.config.openUserConfig\", oni)\n\n    oni.commands.executeCommand(\"oni.config.openUserConfig\")\n\n    await oni.automation.waitFor(() => {\n        return oni.editors.activeEditor.activeBuffer.language === \"typescript\"\n    }, 10000)\n\n    await oni.automation.waitFor(() => {\n        return oni.editors.activeEditor.activeBuffer.lineCount > 0\n    })\n\n    const bufferLines = await oni.editors.activeEditor.activeBuffer.getLines(0, 100)\n    const allLines = bufferLines.join()\n\n    // Validate that the configuration was loaded correctly, and it is the javascript configuration\n    assert.ok(allLines.indexOf(\"oni-api\") >= 0, \"Validate oni-api line is present\")\n    assert.ok(allLines.indexOf(\"activate\") >= 0, \"Validate activate method is present\")\n    assert.strictEqual(oni.editors.activeEditor.activeBuffer.language, \"typescript\")\n}\n\nexport const settings = {\n    configPath: emptyConfigPath,\n}\n"
  },
  {
    "path": "test/ci/Editor.BufferModifiedState.ts",
    "content": "/**\n * Test script to validate the modified status for buffers.\n */\n\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getElementByClassName, getSelectedTabElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni)\n\n    // Check the buffer did not have a modified state by default\n    // let tabState = getElementByClassName(\"tab selected not-dirty\")\n    const tabState1 = getSelectedTabElement({ dirty: false })\n\n    assert.ok(tabState1, \"Check buffer has no modified icon\")\n\n    // Next, edit the buffer and check that shows up\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n\n    oni.automation.sendKeys(\"Buffer has been edited.\")\n    oni.automation.sendKeys(\"<esc>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n\n    // tabState = getElementByClassName(\"tab selected is-dirty\")\n    const tabState2 = getSelectedTabElement({ dirty: true })\n\n    assert.ok(tabState2, \"Check buffer now has a modified icon\")\n\n    // Finally, swap buffer and swap back to ensure the modified status remains.\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"e buffer2\")\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.id === \"2\")\n\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"buf 1\")\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.id === \"1\")\n\n    // tabState = getElementByClassName(\"tab selected is-dirty\")\n    const tabState3 = getSelectedTabElement({ dirty: true })\n\n    assert.ok(tabState3, \"Check buffer still has modified icon after swapping\")\n}\n\n// Bring in custom config.\nexport const settings = {\n    config: {\n        \"tabs.mode\": \"buffers\",\n    },\n}\n"
  },
  {
    "path": "test/ci/Editor.BuffersCursorTest.ts",
    "content": "/*\n * Test Cursor functionality of oni buffers\n *\n */\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getTemporaryFilePath, insertText, navigateToFile } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    createNewFile(\"ts\", oni)\n    await insertText(oni, \"console.log('apple')\")\n\n    const activeBuffer: any = oni.editors.activeEditor.activeBuffer\n\n    const { cursorOffset } = activeBuffer\n\n    assert.equal(cursorOffset, 20)\n\n    // Test that a cursor offset is correctly converted to a line and character\n    // results are 0 based\n    const { line, character } = await activeBuffer.convertOffsetToLineColumn(cursorOffset)\n\n    assert.equal(line, 0)\n    assert.equal(character, 19)\n    // Check that the cursor position from the conversion matches the getCursorPosition method\n    // results\n    const {\n        line: currentLine,\n        character: currentCharacter,\n    } = await activeBuffer.getCursorPosition()\n\n    assert.strictEqual(line, currentLine)\n    assert.strictEqual(currentCharacter, character)\n}\n"
  },
  {
    "path": "test/ci/Editor.CloseTabWithTabModesTabsTest.ts",
    "content": "import * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { getAllTabs, getElementsBySelector, getTabCloseButtonByIndex } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    const getTabsCount = () => getAllTabs().length\n    const waitForTabCount = count => oni.automation.waitFor(() => getTabsCount() === count)\n\n    const openTab = () => {\n        const initialTabCount = getTabsCount()\n        oni.automation.sendKeys(\":tabnew\")\n        oni.automation.sendKeys(\"<cr>\")\n        return waitForTabCount(initialTabCount + 1)\n    }\n\n    const closeLastTabWithMouse = () => {\n        const tabs = getAllTabs()\n        const closeButton = getTabCloseButtonByIndex(tabs.length - 1)\n        closeButton.click()\n        return waitForTabCount(tabs.length - 1)\n    }\n\n    await oni.automation.waitForEditors()\n\n    // 1. Create two tabs, then close the last on\n    await openTab()\n    await openTab()\n    await closeLastTabWithMouse()\n\n    // 3. Open another tab\n    await openTab()\n\n    // 4.1 Attempt to close it\n    await closeLastTabWithMouse()\n}\n\n// Bring in custom config.\nexport const settings = {\n    config: {\n        \"tabs.mode\": \"tabs\",\n    },\n}\n"
  },
  {
    "path": "test/ci/Editor.ExternalCommandLineTest.ts",
    "content": "/**\n * Test script to validate the external command line\n */\n\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { getElementByClassName } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    oni.automation.sendKeys(\":\")\n\n    await oni.automation.waitFor(() => !!getElementByClassName(\"command-line\"))\n\n    assert.ok(!!getElementByClassName(\"command-line\"), \"Validate command line UI is shown\")\n}\n\n// Bring in custom config to turn off animations, in order to reduce noise.\nexport const settings = {\n    config: {\n        \"experimental.commandline.mode\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/Editor.NextPreviousErrorTest.ts",
    "content": "/**\n * Test that you can jump to the next/previous error\n */\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getTemporaryFilePath, navigateToFile } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    const filePath = createBrokenTypescriptFile()\n    await oni.automation.waitForEditors()\n\n    // open file with typescript errors\n    navigateToFile(filePath, oni)\n\n    // modify the buffer to trigger error checking\n    oni.automation.sendKeys(\"O\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n    oni.automation.sendKeys(\"<esc>\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n\n    // wait for 3 errors to be highlighted\n    await oni.automation.waitFor(() => {\n        // @ts-ignore getErrors() is not exposed in the plugin API\n        const errors = oni.diagnostics.getErrors()\n        return (\n            errors[filePath] &&\n            errors[filePath] &&\n            errors[filePath][\"language-typescript\"] &&\n            errors[filePath][\"language-typescript\"].length === 3\n        )\n    }, 120000)\n\n    // nextError jumps to 1st error\n    oni.commands.executeCommand(\"oni.editor.nextError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 5 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 0,\n    )\n\n    // nextError jumps to 2nd error\n    oni.commands.executeCommand(\"oni.editor.nextError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 7 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 7,\n    )\n\n    // nextError jumps to 3rd error\n    oni.commands.executeCommand(\"oni.editor.nextError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 9 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 0,\n    )\n\n    // nextError jumps back up to 1st error\n    oni.commands.executeCommand(\"oni.editor.nextError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 5 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 0,\n    )\n\n    // nextError jumps to 2nd error\n    oni.commands.executeCommand(\"oni.editor.nextError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 7 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 7,\n    )\n\n    // previousError jumps to 1st error\n    oni.commands.executeCommand(\"oni.editor.previousError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 5 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 0,\n    )\n\n    // previousError jumps back down to 3rd error\n    oni.commands.executeCommand(\"oni.editor.previousError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 9 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 0,\n    )\n\n    // previousError jumps to 2nd error\n    oni.commands.executeCommand(\"oni.editor.previousError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 7 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 7,\n    )\n\n    // previousError jumps to 1st error\n    oni.commands.executeCommand(\"oni.editor.previousError\")\n    await oni.automation.waitFor(\n        () =>\n            oni.editors.activeEditor.activeBuffer.cursor.line === 5 &&\n            oni.editors.activeEditor.activeBuffer.cursor.column === 0,\n    )\n}\n\nimport * as fs from \"fs\"\nimport * as os from \"os\"\n\nconst createBrokenTypescriptFile = (): string => {\n    const filePath = getTemporaryFilePath(\"ts\")\n    const content = `\nfunction helloWorld() {\n    console.log('Hello World')\n}\n\nheloWorld()\nhelloWorld()\nwindow.nonExistentThing.goodByeWorld()\nhelloWorld()\nhelloWrld()\n    `.trim()\n\n    fs.writeFileSync(filePath, content)\n    return filePath.replace(/\\\\/g, \"/\")\n}\n"
  },
  {
    "path": "test/ci/Editor.OpenFile.PathWithSpacesTest.ts",
    "content": "/**\n * Test script to validate opening a path with spaces works as expected.\n *\n * Regression test for #1681\n */\n\nimport * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\nimport * as Oni from \"oni-api\"\n\nconst folderName = \"folder with spaces\"\nconst fileName = \"file with spaces.txt\"\nconst createTestFile = (): string => {\n    const fileFullPath = path.join(\n        os.tmpdir(),\n        new Date().getTime().toString(),\n        folderName,\n        fileName,\n    )\n    mkdirp.sync(path.dirname(fileFullPath))\n    fs.writeFileSync(fileFullPath, \"test contents\")\n    return fileFullPath\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    const file = createTestFile()\n\n    await oni.editors.activeEditor.openFile(file, { openMode: Oni.FileOpenMode.Edit })\n\n    const openFiles = oni.editors.activeEditor.getBuffers()\n    assert.strictEqual(openFiles.length, 1, \"Validate a single buffer was opened\")\n    assert.strictEqual(openFiles[0].filePath, file, \"Validate the filepath was correct\")\n}\n"
  },
  {
    "path": "test/ci/Editor.ScrollEventTest.ts",
    "content": "/**\n * Test script to validate the modified status for tabs.\n */\n\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getElementByClassName } from \"./Common\"\n\nimport * as os from \"os\"\nconst createLines = (num: number): string => {\n    const ret = []\n\n    for (let i = 0; i < num; i++) {\n        ret.push(i)\n    }\n\n    return ret.join(os.EOL)\n}\n\nconst assertValue = (actual: number, expected: number, msg: string, oni: Oni.Plugin.Api) => {\n    const passed = actual === expected\n\n    const notification = oni.notifications.createItem()\n    const title = passed ? \"Assertion Passed\" : \"Assertion Failed\"\n    notification.setContents(title, `${msg}\\nActual: ${actual}\\nExpected:${expected}`)\n    ;(notification as any).setLevel(passed ? \"success\" : \"error\")\n    notification.show()\n\n    assert.strictEqual(actual, expected, msg)\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni, createLines(500))\n\n    let scrollEventHitCount = 0\n\n    oni.editors.activeEditor.onBufferScrolled.subscribe(() => {\n        scrollEventHitCount++\n    })\n\n    await oni.automation.sendKeys(\"G\")\n\n    await oni.automation.waitFor(() => scrollEventHitCount === 1)\n    assertValue(scrollEventHitCount, 1, \"A single scroll event should've been triggered by G\", oni)\n\n    await oni.automation.sendKeys(\"gg\")\n    await oni.automation.waitFor(() => scrollEventHitCount === 2)\n    assertValue(scrollEventHitCount, 2, \"Another scroll event should've been triggered by gg\", oni)\n\n    await oni.automation.sendKeys(\":50<cr>\")\n    await oni.automation.waitFor(() => scrollEventHitCount === 3)\n    assertValue(\n        scrollEventHitCount,\n        3,\n        \"Another scroll event should've been triggered by navigating to a line\",\n        oni,\n    )\n\n    await oni.automation.sendKeys(\"<c-e>\")\n    await oni.automation.waitFor(() => scrollEventHitCount === 4)\n    assertValue(\n        scrollEventHitCount,\n        4,\n        \"Another scroll event should've been triggered by scrolling up one line\",\n        oni,\n    )\n\n    await oni.automation.sendKeys(\"<c-d>\")\n    await oni.automation.waitFor(() => scrollEventHitCount === 5)\n    assertValue(\n        scrollEventHitCount,\n        5,\n        \"Another scroll event should've been triggered by scrolling down one line\",\n        oni,\n    )\n}\n"
  },
  {
    "path": "test/ci/Editor.TabModifiedState.ts",
    "content": "/**\n * Test script to validate the modified status for tabs.\n */\n\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getElementByClassName, getSelectedTabElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni)\n\n    // Check the buffer did not have a modified state by default\n    // let tabState = getElementByClassName(\"tab selected not-dirty\")\n    const tabState1 = getSelectedTabElement({ dirty: false })\n\n    assert.ok(tabState1, \"Check tab has no modified icon\")\n\n    // Next, edit the buffer and check that shows up\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n\n    oni.automation.sendKeys(\"Buffer has been edited.\")\n    oni.automation.sendKeys(\"<esc>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n\n    // tabState = getElementByClassName(\"tab selected is-dirty\")\n    const tabState2 = getSelectedTabElement({ dirty: true })\n\n    assert.ok(tabState2, \"Check tab now has a modified icon\")\n\n    // Next, open a split in the current tab, and check the tab still remains dirty\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"vsplit buffer2\")\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.id === \"2\")\n\n    // tabState = getElementByClassName(\"tab selected is-dirty\")\n\n    assert.ok(tabState2, \"Check tab has modified icon after opening split\")\n\n    // Finally, swap tab and swap back to ensure the modified status remains.\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"tabe buffer3\")\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.id === \"3\")\n\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"tabn 1\")\n    oni.automation.sendKeys(\"<enter>\")\n\n    // This should be buf 2, since that was the last buffer we were in before swapping to\n    // the second tab.\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.id === \"2\")\n\n    // tabState = getElementByClassName(\"tab selected is-dirty\")\n    const tabState3 = getSelectedTabElement({ dirty: true })\n\n    assert.ok(tabState3, \"Check tab still has modified icon after swapping\")\n}\n\n// Bring in custom config.\nexport const settings = {\n    config: {\n        \"tabs.mode\": \"tabs\",\n    },\n}\n"
  },
  {
    "path": "test/ci/Explorer.LocateBufferTest.ts",
    "content": "/**\n * Test script to validate explorer locating currently open buffer\n */\n\nimport * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\nimport * as Log from \"oni-core-logging\"\n\nimport { getElementsBySelector, navigateToFile, useTempWorkspace, waitForCommand } from \"./Common\"\n\nconst command = \"explorer.locate.buffer\"\nconst fileToLocate = \"File.ts\"\n\nconst isFileToLocateVisibleAndHighlighted = () => {\n    return !![].slice\n        .call(getElementsBySelector(\"div.item > div[icon]\"))\n        .filter(el => getComputedStyle(el)[\"background-color\"] !== \"rgba(0, 0, 0, 0)\")\n        .map(el => el.parentElement.textContent)\n        .filter(text => text === fileToLocate).length\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n    // Wait for sidebar split to appear\n    await oni.automation.waitFor(() => document.querySelectorAll(\".sidebar-content\").length === 1)\n    // Ensure command exists.\n    await waitForCommand(command, oni)\n    // Switch to temporary workspace.\n    const rootPath = await useTempWorkspace(oni)\n    // Open file in workspace.\n    await navigateToFile(path.join(rootPath, \"src\", fileToLocate), oni)\n    // File shouldn't yet be shown in the explorer.\n    await oni.automation.waitFor(() => !isFileToLocateVisibleAndHighlighted())\n    // Execute the command to locate the file in the explorer.\n    oni.commands.executeCommand(command)\n    // File should now be shown in the explorer.\n    await oni.automation.waitFor(() => isFileToLocateVisibleAndHighlighted())\n    // What happens if we hide the sidebar?\n    await oni.commands.executeCommand(\"sidebar.toggle\")\n    // File is no longer shown in the explorer.\n    await oni.automation.waitFor(() => !isFileToLocateVisibleAndHighlighted())\n    // Execure the command to locate the file in the explorer.\n    oni.commands.executeCommand(command)\n    // File should now be shown in the explorer.\n    await oni.automation.waitFor(() => isFileToLocateVisibleAndHighlighted())\n}\n"
  },
  {
    "path": "test/ci/IndentGuide.BufferLayerTest.tsx",
    "content": "/**\n * Test script for the Indent Lines Layer.\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nconst testStr = `\n    function doThing() {\n        thingOne();\n        thingTwo();\n    }\n\n    const X = a + b\n    const Y = c - d\n`\n\nconst getIndentLines = () => document.querySelectorAll(\"[data-id='indent-line']\")\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni, testStr)\n\n    const elements = getIndentLines()\n\n    const element = elements[0]\n\n    assert.ok(element, \"Validate an indent line is present in the layer\")\n\n    // Render the same test string in an incompatible buffer and plugin should not render\n    await createNewFile(\"md\", oni, testStr)\n    const markdownIndents = getIndentLines()\n\n    assert.ok(markdownIndents.length === 0, \"No indents are rendered in an incompatible file\")\n}\n\nexport const settings = {\n    config: {\n        \"oni.useDefaultConfig\": true,\n        \"oni.loadInitVim\": false,\n        \"experimental.indentLines.enabled\": true,\n        \"experimental.indentLines.bannedFiletypes\": [\".md\"],\n        \"_internal.hasCheckedInitVim\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/LargeFileTest.ts",
    "content": "/**\n * Test for opening a large file\n *\n * Regression test for #1064\n */\n\nimport * as Oni from \"oni-api\"\n\nimport { getTemporaryFilePath, navigateToFile } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    const filePath = createLargeTestFile()\n    await oni.automation.waitForEditors()\n\n    navigateToFile(filePath, oni)\n\n    oni.automation.sendKeys(\"G\")\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.cursor.line === 99999,\n        30000,\n    )\n\n    oni.automation.sendKeys(\":50000<CR>\")\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.cursor.line === 49999,\n        30000,\n    )\n\n    oni.automation.sendKeys(\"gg\")\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.cursor.line === 0,\n        30000,\n    )\n}\n\nimport * as fs from \"fs\"\nimport * as os from \"os\"\n\nconst createLargeTestFile = (): string => {\n    const filePath = getTemporaryFilePath(\"js\")\n    const line =\n        \"window.alert('hello world from a very very very very extremely large javascript file'); // testing testing testing to make the line very long\"\n\n    const lineCount = 100 * 1000\n\n    const lines = []\n    for (let i = 0; i < lineCount; i++) {\n        lines.push(line + os.EOL)\n    }\n\n    fs.writeFileSync(filePath, lines)\n    return filePath\n}\n"
  },
  {
    "path": "test/ci/LargePasteTest.ts",
    "content": "/**\n * Test for pasting a large number of lines\n *\n * Regression test for #2414\n */\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\nimport {\n    createNewFile,\n    getElementByClassName,\n    getTemporaryFilePath,\n    navigateToFile,\n} from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    const filePath = createLargeTestFile()\n    await oni.automation.waitForEditors()\n\n    // open file with 2000 lines\n    navigateToFile(filePath, oni)\n\n    // select everything\n    oni.automation.sendKeys(\"<s-v>\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"visual\")\n    oni.automation.sendKeys(\"G\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.cursor.line === 1999)\n\n    // copy and paste should result in 4000 lines\n    await copy(oni)\n    oni.automation.sendKeys(\"o\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n    await paste(oni, () => oni.editors.activeEditor.activeBuffer.lineCount === 4001)\n    assert.strictEqual(oni.editors.activeEditor.activeBuffer.lineCount, 4001)\n\n    // go to first line, and copy first word ('this')\n    oni.automation.sendKeys(\"gg\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.cursor.line === 0)\n    oni.automation.sendKeys(\"v\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"visual\")\n    oni.automation.sendKeys(\"e\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.cursor.column === 3)\n    await copy(oni)\n\n    // paste in the middle of the first word\n    oni.automation.sendKeys(\"3l\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.cursor.column === 3)\n    oni.automation.sendKeys(\"i\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n    await paste(oni, () => oni.editors.activeEditor.activeBuffer.cursor.column === 7)\n\n    const [firstLine] = await oni.editors.activeEditor.activeBuffer.getLines(0, 1)\n    assert.strictEqual(\n        firstLine,\n        \"thithiss is a line of 'text' that will be repeated a bunch of times to make for a large wall of 'text' to paste\",\n    )\n\n    // type ':' and paste the text into the command line\n    oni.automation.sendKeys(\":\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"cmdline_normal\")\n    await paste(oni, () => {\n        const commandLine = getElementByClassName(\"command-line\")\n        return commandLine && commandLine.textContent === \":this\"\n    })\n}\n\nimport * as fs from \"fs\"\nimport * as os from \"os\"\n\nconst createLargeTestFile = (): string => {\n    const filePath = getTemporaryFilePath(\"js\")\n    const line =\n        \"this is a line of 'text' that will be repeated a bunch of times to make for a large wall of 'text' to paste\"\n\n    const lines = []\n    for (let i = 0; i < 2000; i++) {\n        lines.push(line)\n    }\n\n    fs.writeFileSync(filePath, lines.join(os.EOL))\n    return filePath\n}\n\nimport { isMac } from \"../../browser/src/Platform\"\n\nconst copy = async (oni: Oni.Plugin.Api) => {\n    if (isMac()) {\n        oni.automation.sendKeys(\"<m-c>\")\n    } else {\n        oni.automation.sendKeys(\"<c-c>\")\n    }\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n}\n\nconst paste = async (\n    oni: Oni.Plugin.Api,\n    waitConditionChecker: Oni.Automation.WaitConditionChecker,\n) => {\n    if (isMac()) {\n        oni.automation.sendKeys(\"<m-v>\")\n    } else {\n        oni.automation.sendKeys(\"<c-v>\")\n    }\n\n    await oni.automation.waitFor(waitConditionChecker)\n\n    oni.automation.sendKeys(\"<esc>\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n}\n"
  },
  {
    "path": "test/ci/MarkdownPreviewTest.tsx",
    "content": "/**\n * Test the Markdown-preview plugin\n */\n\nimport { Assertor } from \"./Assert\"\nimport {\n    awaitEditorMode,\n    getElementByClassName,\n    getTemporaryFilePath,\n    insertText,\n    navigateToFile,\n} from \"./Common\"\n\nimport * as Oni from \"oni-api\"\n\ninterface IMarkdownPreviewPlugin {\n    isPaneOpen(): boolean\n    getUnrenderedContent(): string\n    getRenderedContent(): string\n    toggle(): void\n}\n\nexport const settings = {\n    config: {\n        \"experimental.markdownPreview.enabled\": true,\n    },\n}\n\nexport async function test(oni: Oni.Plugin.Api) {\n    const assert = new Assertor(\"Markdown-preview\")\n\n    await oni.automation.waitForEditors()\n\n    // Wait for Plugin to be loaded\n    await oni.automation.waitFor(() => oni.plugins.loaded)\n    const markdownPlugin = oni.plugins.getPlugin(\n        \"oni-plugin-markdown-preview\",\n    ) as IMarkdownPreviewPlugin\n    assert.defined(markdownPlugin, \"plugin instance\")\n\n    // Check its not open by default\n    assert.assert(!markdownPlugin.isPaneOpen(), \"Preview pane is initially closed.\")\n\n    // Check it opens when navigating into a markdown file.\n    const markdownFilePath = getTemporaryFilePath(\"md\")\n    await navigateToFile(markdownFilePath, oni)\n    await oni.automation.waitFor(() => markdownPlugin.isPaneOpen())\n\n    assert.isEmpty(\n        markdownPlugin.getUnrenderedContent().trim(),\n        \"Preview pane shown for Markdown buffer.\",\n    )\n\n    // Check a Title is rendered correctly.\n    await insertText(oni, \"# Title 1\")\n    assert.contains(\n        markdownPlugin.getRenderedContent(),\n        \">Title 1</h1>\",\n        \"Preview pane with renders header element.\",\n    )\n\n    // Check syntax highlights are applied.\n    oni.automation.sendKeys(\"o\")\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"insert\")\n\n    oni.automation.sendKeys(\"```<enter>\")\n    oni.automation.sendKeys(\"const test = 'Oni'<enter>\")\n    oni.automation.sendKeys(\"```\")\n    oni.automation.sendKeys(\"<esc>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.mode === \"normal\")\n\n    assert.contains(\n        markdownPlugin.getRenderedContent(),\n        \"code>\",\n        \"Code block present in preview HTML.\",\n    )\n\n    assert.assert(\n        getElementByClassName(\"hljs-keyword\").innerText === \"const\",\n        \"Syntax highlights present in preview HTML.\",\n    )\n\n    // Finally, test swapping between files.\n    // Swapping to a non-MD file should close it.\n    // Swapping to an MD file should open it.\n    // Closing the MD preview manually should cause it to remain closed.\n\n    const nonMDFilePath = getTemporaryFilePath(\"ts\")\n\n    await navigateToFile(nonMDFilePath, oni)\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.language === \"typescript\",\n    )\n    assert.assert(!markdownPlugin.isPaneOpen(), \"Preview pane is closed for non-MD file.\")\n\n    await navigateToFile(markdownFilePath, oni)\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.language === \"markdown\",\n    )\n    assert.assert(markdownPlugin.isPaneOpen(), \"Preview pane opens for MD file.\")\n\n    // Manually closing preview, should remain closed now.\n    markdownPlugin.toggle()\n    assert.assert(!markdownPlugin.isPaneOpen(), \"Preview pane closes on toggle.\")\n\n    await navigateToFile(nonMDFilePath, oni)\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.language === \"typescript\",\n    )\n    await navigateToFile(markdownFilePath, oni)\n    await oni.automation.waitFor(\n        () => oni.editors.activeEditor.activeBuffer.language === \"markdown\",\n    )\n\n    // Should remain closed when swapping back in.\n    assert.assert(\n        !markdownPlugin.isPaneOpen(),\n        \"Preview pane remains closed for MD file when manually closed.\",\n    )\n}\n"
  },
  {
    "path": "test/ci/Neovim.CallOniCommands.ts",
    "content": "/**\n * Test script to validate calling Oni commands from Neovim\n */\n\nimport * as assert from \"assert\"\nimport * as Oni from \"oni-api\"\n\nimport { getElementByClassName } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Open the commandline and open the QuickOpen Menu.\n    oni.automation.sendKeys(\":\")\n    await oni.automation.waitFor(() => !!getElementByClassName(\"command-line\"))\n    oni.automation.sendKeys('call OniCommand(\"quickOpen.show\")')\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() => oni.menu.isMenuOpen())\n    assert(oni.menu.isMenuOpen(), \"Check menu opened correctly.\")\n\n    oni.commands.executeCommand(\"menu.close\")\n\n    // Now test passing optional arguments\n    // Create a test command to call, but could be swapped to use the browser\n    // when more easily accessible.\n    oni.commands.registerCommand({\n        command: \"ciTest.test\",\n        name: \"Test passing over args.\",\n        detail: \"Opens a file.\",\n        execute: (file?: string) => oni.editors.activeEditor.neovim.command(`:e ${file}`),\n    })\n    await oni.automation.sleep(500)\n\n    oni.automation.sendKeys(\":\")\n    await oni.automation.waitFor(() => !!getElementByClassName(\"command-line\"))\n    oni.automation.sendKeys('call OniCommand(\"ciTest.test\", \"testFile\")')\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() =>\n        oni.editors.activeEditor.activeBuffer.filePath.endsWith(\"testFile\"),\n    )\n\n    const currentBuffer = oni.editors.activeEditor.activeBuffer.filePath\n\n    assert(\n        currentBuffer.endsWith(\"testFile\"),\n        \"Check file opened correctly after being passed over.\",\n    )\n\n    // Finally test passing multiple optional arguments\n    oni.commands.registerCommand({\n        command: \"ciTest.test2\",\n        name: \"Test passing over args.\",\n        detail: \"Opens multiple files.\",\n        execute: (files?: string[]) => {\n            files.forEach(file => oni.editors.activeEditor.neovim.command(`:e ${file}`))\n        },\n    })\n    await oni.automation.sleep(500)\n\n    oni.automation.sendKeys(\":\")\n    await oni.automation.waitFor(() => !!getElementByClassName(\"command-line\"))\n    oni.automation.sendKeys(\n        'call OniCommand(\"ciTest.test2\", \"testFile2\", \"testFile3\", \"testFile4\")',\n    )\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.id === \"4\")\n\n    const currentBufferId = oni.editors.activeEditor.activeBuffer.id\n\n    assert(\n        currentBufferId === \"4\",\n        \"Check multiple files opened correctly after being passed over.\",\n    )\n}\n"
  },
  {
    "path": "test/ci/Neovim.InvalidInitVimHandlingTest.ts",
    "content": "/**\n * Test script to verify the scenario where init.vim has an error\n *\n * In that case, a notification should pop up, but the editor should still load.\n */\n\nimport * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { getTemporaryFilePath } from \"./Common\"\n//\n// tslint:disable:no-console\n\nconst createInitVim = (): string => {\n    const tempInitVim = getTemporaryFilePath(\"vim\")\n\n    console.log(\"- Writing init vim to: \" + tempInitVim)\n    fs.writeFileSync(tempInitVim, \"derpInvalidInitVimderp\")\n    console.log(\"- Write successful.\")\n\n    return tempInitVim\n}\n\nconst getNotificationElements = () => {\n    const elements = document.body.getElementsByClassName(\"notification\")\n\n    if (!elements || !elements.length) {\n        return null\n    } else {\n        return elements\n    }\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    // Wait for install help UX to show\n    await oni.automation.waitFor(() => !!getNotificationElements())\n\n    const notificationElements = getNotificationElements()\n\n    assert.strictEqual(notificationElements.length, 1, \"Validate there is a single notification\")\n\n    const notificationText = notificationElements[0].textContent\n    const containsInitVim = notificationText.indexOf(\"init.vim\") >= 0\n\n    assert.ok(containsInitVim, \"Validate error notification contains the text 'init.vim'\")\n\n    // Validate editors still load\n    await oni.automation.waitForEditors()\n\n    assert.ok(\"Editors loaded successfully.\")\n}\n\nexport const settings = {\n    config: {\n        \"oni.loadInitVim\": createInitVim(),\n    },\n    allowLogFailures: true,\n}\n"
  },
  {
    "path": "test/ci/NoInstalledNeovim.config.js",
    "content": "// For more information on customizing Oni,\n// check out our wiki page:\n// https://github.com/onivim/oni/wiki/Configuration\n\nmodule.exports = {\n    \"debug.neovimPath\": \"/derp/not-a-valid-neovim-binary\",\n};\n"
  },
  {
    "path": "test/ci/NoInstalledNeovim.ts",
    "content": "/**\n * Test script to verify the scenario where no neovim is installed\n *\n * We should be showing a descriptive error message...\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nconst getInstallHelpElement = () => {\n    const elements = document.body.getElementsByClassName(\"install-help\")\n\n    if (!elements || !elements.length) {\n        return null\n    } else {\n        return elements[0]\n    }\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    // Wait for install help UX to show\n    await oni.automation.waitFor(() => getInstallHelpElement() !== null)\n\n    assert.ok(true, \"Found install help content as expected.\")\n}\n\nexport const settings = {\n    configPath: \"NoInstalledNeovim.config.js\",\n    allowLogFailures: true,\n}\n"
  },
  {
    "path": "test/ci/OSX.WindowTitleTest.ts",
    "content": "/**\n * Test script to validate the window title is rendered\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\n\nimport { createNewFile } from \"./Common\"\n\nexport const test = async (oni: any) => {\n    await oni.automation.waitForEditors()\n\n    // Create a file that doesn't have a language associated with it, to minimize noise\n    await createNewFile(\"test_file\", oni)\n\n    // Validate that the titlebar element eventually shows ONI + the file name\n    await oni.automation.waitFor(() => {\n        const titleBar = document.getElementById(\"oni-titlebar\")\n        return (\n            titleBar.textContent.indexOf(\"ONI\") >= 0 &&\n            titleBar.textContent.indexOf(\"test_file\") >= 0\n        )\n    })\n}\n"
  },
  {
    "path": "test/ci/PaintPerformanceTest.config.js",
    "content": "// For more information on customizing Oni,\n// check out our wiki page:\n// https://github.com/onivim/oni/wiki/Configuration\n// tslint:disable\nmodule.exports = {\n    \"sidebar.enabled\": false,\n    \"statusbar.enabled\": false,\n    \"tabs.mode\": \"hidden\",\n    \"ui.animations.enabled\": false,\n}\n"
  },
  {
    "path": "test/ci/PaintPerformanceTest.ts",
    "content": "/**\n * Test script to valid performance/responsiveness of the typing scenario\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\n\nimport { Rectangle, remote } from \"electron\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile, getCompletionElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Create a file that doesn't have a language associated with it, to minimize noise\n    await createNewFile(\"test_file\", oni)\n\n    oni.automation.sendKeys(\"i\")\n\n    // Fire a couple of initial key presses to warm up -\n    // there is some expected rendering noise here (like the 'modified' icon in the tab)\n\n    for (let i = 0; i < 5; i++) {\n        await oni.automation.sleep(100)\n        oni.automation.sendKeys(\".\")\n    }\n\n    const gpuFeatureStatus = remote.app.getGPUFeatureStatus()\n    console.log(\"[PaintPerformance] gpuFeatureStatus: \" + JSON.stringify(gpuFeatureStatus)) // tslint:disable-line\n\n    // Unfortunately, if gpu compositing is not enabled, we can't test in as fine grained way\n    const gpuCompositingEnabled = gpuFeatureStatus.gpu_compositing === \"enabled\"\n\n    // There are two metrics we want to measure now:\n    // - Number of style elements\n    // - Size of paint rectangles\n\n    const startHeadCount = document.head.querySelectorAll(\"*\").length\n    const startBodyCount = document.body.querySelectorAll(\"*\").length\n\n    const currentWindow = remote.getCurrentWindow()\n    const currentWebContents = currentWindow.webContents\n\n    const paintRectangles: Rectangle[] = []\n\n    currentWebContents.beginFrameSubscription(true, (buffer, dirtyRect) => {\n        console.log(\"[PaintPerformance] dirtyRect: \" + JSON.stringify(dirtyRect)) // tslint:disable-line\n        paintRectangles.push(dirtyRect)\n    })\n\n    // We'll type out another 5 characters...\n    for (let i = 0; i < 5; i++) {\n        await oni.automation.sleep(100)\n        oni.automation.sendKeys(\".\")\n    }\n\n    await oni.automation.sleep(100)\n\n    const endHeadCount = document.head.querySelectorAll(\"*\").length\n    const endBodyCount = document.body.querySelectorAll(\"*\").length\n\n    assert.strictEqual(\n        startHeadCount,\n        endHeadCount,\n        \"There should be no items added to the head over the course of typing.\",\n    )\n    assert.strictEqual(\n        startBodyCount,\n        endBodyCount,\n        \"There should be no items added to the body over the course of typing.\",\n    )\n\n    // TODO: Unfortunately, the `beginFrameSubscription` events don't seem to come through\n    // on the OSX TravisCI machine. It would be great to unblock this, but for now,\n    // we'll only exercise the paint rectangle validation on Windows:\n    if (os.platform() !== \"win32\") {\n        console.warn(\"Aborting remaining validations because it isn't a Windows machine.\") // tslint:disable-line\n        return\n    }\n\n    assert.ok(paintRectangles.length >= 5, \"There should be at least 5 paint rectangles\")\n\n    // If gpu compositing is enabled, the browser can take advantage of the cursor and related components\n    // being in its own layer, and minimize repaints. Otherwise, it seems that the browser renders in 256 pixel chunks.\n    // We'll still test for it, as it can still catch cases where we'd have larger repaint errors.\n    const maxHeight = gpuCompositingEnabled ? 20 : 256\n\n    paintRectangles.forEach(pr => {\n        // TODO: #1129 - Validate width as well!\n\n        assert.ok(pr.height <= maxHeight, \"Validate rectangle height is less than the max height\")\n    })\n}\n\n// Bring in custom config to turn off animations, in order to reduce noise.\nexport const settings = {\n    configPath: \"PaintPerformanceTest.config.js\",\n}\n"
  },
  {
    "path": "test/ci/PrettierPluginTest.ts",
    "content": "/**\n * Test the Prettier plugin\n */\n\nimport * as stock_assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport { Assertor } from \"./Assert\"\nimport {\n    awaitEditorMode,\n    createNewFile,\n    getElementByClassName,\n    getTemporaryFilePath,\n    insertText,\n    navigateToFile,\n    useTempWorkspace,\n} from \"./Common\"\n\nimport * as Oni from \"oni-api\"\n\ninterface IPluginManager {\n    getPlugin(name: string): any\n}\n\ninterface IPrettierPlugin {\n    checkCompatibility(filePath: string): boolean\n    applyPrettier(): void\n    checkPrettierrc(): boolean\n}\n\nexport const settings = {\n    config: {\n        \"oni.useDefaultConfig\": true,\n        \"oni.loadInitVim\": false,\n        \"oni.plugins.prettier\": {\n            settings: {\n                semi: false,\n                tabWidth: 2,\n                useTabs: false,\n                singleQuote: false,\n                trailingComma: \"es5\",\n                bracketSpacing: true,\n                jsxBracketSameLine: false,\n                arrowParens: \"avoid\",\n                printWidth: 80,\n            },\n            formatOnSave: true,\n            enabled: true,\n            allowedFiletypes: [\".js\", \".jsx\", \".ts\", \".tsx\", \".md\", \".html\", \".json\", \".graphql\"],\n        },\n    },\n}\n\nexport async function test(oni: Oni.Plugin.Api) {\n    const assert = new Assertor(\"Prettier-plugin\")\n    await oni.automation.waitForEditors()\n    await oni.automation.waitFor(() => oni.plugins.loaded)\n    // Switch to temporary workspace.\n    const rootPath = await useTempWorkspace(oni)\n    // Open file in workspace.\n    await navigateToFile(path.join(rootPath, \"src\", \"File.ts\"), oni)\n    // Insert text to be prettified.\n    await insertText(oni, \"function test(){console.log('test')};\")\n    // Assert that plugin exists.\n    const prettierPlugin: IPrettierPlugin = await oni.plugins.getPlugin(\"oni-plugin-prettier\")\n    assert.defined(prettierPlugin, \"plugin instance\")\n    assert.defined(prettierPlugin.applyPrettier, \"plugin formatting method\")\n    const { activeBuffer } = oni.editors.activeEditor\n    assert.assert(\n        prettierPlugin.checkCompatibility(activeBuffer.filePath),\n        \"If valid filetype prettier plugin check should return true\",\n    )\n\n    // Test that in a Typescript file the plugin formats the buffer on save\n    oni.automation.sendKeys(\"0\")\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"w\")\n    oni.automation.sendKeys(\"<enter>\")\n\n    await oni.automation.sleep(5000)\n\n    const bufferText = await activeBuffer.getLines()\n    const bufferString = bufferText.join(os.EOL)\n    assert.assert(!bufferString.includes(\";\"), \"Semi colons are removed from the text\")\n    assert.assert(!bufferString.includes(\"'\"), \"Single quotes are removed from the formatted text\")\n    assert.assert(bufferText.length === 3, \"The code is split into 3 lines\")\n    // Test that the prettier status bar item is present\n    oni.automation.waitFor(() => !!getElementByClassName(\"prettier\"))\n}\n"
  },
  {
    "path": "test/ci/QuickOpenTest.ts",
    "content": "import * as fs from \"fs\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as path from \"path\"\n\nimport { Assertor } from \"./Assert\"\nimport { useTempWorkspace, waitForCommand } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    const assert = new Assertor(\"QuickOpen\", oni)\n    await oni.automation.waitForEditors()\n    await oni.automation.waitFor(() => oni.plugins.loaded)\n    const instance = oni.plugins.getPlugin(\"oni-plugin-quickopen\")\n    assert.defined(instance, \"plugin instance\")\n\n    await useTempWorkspace(oni)\n\n    // Start\n    console.info(`QuickOpen: Open and close the menu`) // tslint:disable-line no-console\n    oni.commands.executeCommand(\"quickOpen.searchFileByPath\")\n    await oni.automation.waitFor(() => oni.menu.isMenuOpen())\n\n    await waitForCommand(\"menu.close\", oni)\n    oni.commands.executeCommand(\"menu.close\")\n    await oni.automation.waitFor(() => !oni.menu.isMenuOpen())\n    await oni.automation.sleep(100)\n    // End\n\n    // Start\n    console.info(`QuickOpen: File search`) // tslint:disable-line no-console\n    await waitForCommand(\"quickOpen.searchFileByPath\", oni)\n    oni.commands.executeCommand(\"quickOpen.searchFileByPath\")\n    await oni.automation.waitFor(() => oni.menu.isMenuOpen())\n\n    const anyOni = oni as any\n    await oni.automation.sleep(1000)\n    anyOni.automation.sendKeysV2(\"file.ts\")\n    await oni.automation.sleep(2000)\n    anyOni.automation.sendKeysV2(\"<CR>\")\n    const editor = oni.editors.activeEditor\n    await assert.waitFor(() => editor.activeBuffer.filePath, (fp: string) => fp.endsWith(\"File.ts\"))\n    // End\n}\n"
  },
  {
    "path": "test/ci/Regression.1251.NoAdditionalProcessesOnStartup.ts",
    "content": "/**\n * Regression test for #1251\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    const process = oni.process as any\n    const pids = process.getPIDs()\n\n    assert.strictEqual(pids.length, 2, \"Validate that only two processes were spawned on startup\")\n}\n"
  },
  {
    "path": "test/ci/Regression.1295.UnfocusedWindowTest.ts",
    "content": "/**\n * Regression test for #1295\n *\n * Validate that creating a window without focus doesn't crash the app!\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // We'll execute two commands in quick succession:\n    // :vsp\n    // :wincmd p\n    // This creates a new vertical split, and immediately moves back to the previous window\n\n    const neovim = oni.editors.activeEditor.neovim\n\n    const p1 = neovim.command(\":vsp\")\n    const p2 = neovim.command(\":wincmd p\")\n\n    await Promise.all([p1, p1])\n\n    // Not sure of a deterministic way to wait for this, but we need\n    // to wait for a redraw to come back from the editor\n    await oni.automation.sleep(1000)\n\n    const editorElements = document.getElementsByClassName(\"editor\")\n    assert.ok(editorElements.length > 0, \"Validate an editor is still present\")\n}\n"
  },
  {
    "path": "test/ci/Regression.1296.SettingColorsTest.ts",
    "content": "/**\n * Regression test for #1296\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Validate that setting the configuration via 'colors' actually sets the color...\n    oni.configuration.setValues({\n        \"colors.foreground\": \"magenta\",\n        \"colors.editor.foreground\": \"magenta\",\n    })\n\n    // Wait for it to be set on the body..\n    oni.automation.waitFor(() => {\n        const foregroundColor = document.body.style.color\n        return foregroundColor === \"magenta\"\n    })\n}\n"
  },
  {
    "path": "test/ci/Regression.1799.MacroApplicationTest.ts",
    "content": "/**\n * Regression test for #1799\n *\n * Validate that running a large macro operation doesn't crash the editor\n */\n\nimport * as assert from \"assert\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\nimport { getCollateralPath, navigateToFile } from \"./Common\"\n\nconst testCsvFilePath = path.join(getCollateralPath(), \"1799_test.csv\")\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await navigateToFile(testCsvFilePath, oni)\n\n    const activeEditor = oni.editors.activeEditor\n\n    // Record macro\n    await activeEditor.neovim.input(\"qa\")\n\n    // Delete comma from end of line\n    await activeEditor.neovim.input(\"$x\")\n    await activeEditor.neovim.input(\"j0\")\n\n    // End recording\n    await activeEditor.neovim.input(\"q\")\n\n    // Run macro 999 times\n    await activeEditor.neovim.input(\"999@a\")\n\n    // Wait for last line to not end with a comma\n\n    let attempts = 0\n    let editAccomplished = false\n    while (attempts < 5) {\n        const [lastLine] = await activeEditor.activeBuffer.getLines(998, 999)\n\n        if (!lastLine.endsWith(\",\")) {\n            editAccomplished = true\n            break\n        }\n\n        await oni.automation.sleep(1000)\n        attempts++\n    }\n\n    assert.ok(editAccomplished, \"Verify edit applied to last line\")\n\n    await activeEditor.neovim.input(\"G\")\n    await activeEditor.neovim.input(\"gg\")\n\n    await oni.automation.waitFor(() => activeEditor.activeBuffer.cursor.line === 0)\n\n    await activeEditor.neovim.input(\"G\")\n\n    await oni.automation.waitFor(() => activeEditor.activeBuffer.cursor.line === 999)\n}\n"
  },
  {
    "path": "test/ci/Regression.1819.AutoReadCheckTimeTest.ts",
    "content": "/**\n * Regression test for #1819\n *\n * Validate our `vim.setting.autoread` behaves as intended\n */\n\nimport * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport { remote } from \"electron\"\n\nimport * as ShellJS from \"shelljs\"\n\nimport * as Oni from \"oni-api\"\nimport { getTemporaryFilePath, navigateToFile } from \"./Common\"\n\nconst fileName = getTemporaryFilePath(\"txt\")\nconst writeInitialFile = () => {\n    fs.writeFileSync(fileName, \"Hello World\")\n}\n\nconst writeRevision = () => {\n    fs.writeFileSync(fileName, \"Hello Again\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    writeInitialFile()\n\n    await navigateToFile(fileName, oni)\n\n    const windowsAsAny = oni.windows as any\n    windowsAsAny.activeSplit.leave()\n\n    await oni.automation.sleep(500)\n\n    writeRevision()\n    ShellJS.touch(fileName)\n\n    await oni.automation.sleep(500)\n\n    windowsAsAny.activeSplit.enter()\n\n    const activeEditor = oni.editors.activeEditor\n\n    let attempts = 0\n    let editAccomplished = false\n    while (attempts < 5) {\n        oni.log.info(\"Attempt: \" + attempts)\n        const [firstLine] = await activeEditor.activeBuffer.getLines(0, 1)\n        oni.log.info(\"read line: \" + firstLine)\n\n        if (firstLine.indexOf(\"Hello Again\") === 0) {\n            editAccomplished = true\n            break\n        }\n\n        await oni.automation.sleep(1000)\n        attempts++\n    }\n\n    oni.log.info(\"edit accomplished: \" + editAccomplished)\n    assert.ok(editAccomplished, \"Validate the change was picked up\")\n}\n//\n// Bring in custom config.\nexport const settings = {\n    config: {\n        \"vim.setting.autoread\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/Regression.2047.VerifyCanvasIsIntegerSize.ts",
    "content": "/**\n * Regression test for #2047\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nconst isInteger = (num: number) => {\n    return Math.round(num) === num\n}\n\nconst assertCanvasIsIntegerSize = (canvasElement: HTMLElement) => {\n    const rect = canvasElement.getBoundingClientRect()\n    const measuredWidth = rect.width\n    const measuredHeight = rect.height\n\n    assert.ok(isInteger(measuredWidth), \"Validate the canvas's width is an integer value\")\n    assert.ok(isInteger(measuredHeight), \"Validate the canvas's height is an integer value\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    const allCanvasElements = document.getElementsByTagName(\"canvas\")\n\n    assert.ok(allCanvasElements.length > 0, \"Verify there is at least one canvas element\")\n\n    // tslint:disable-next-line\n    for (let i = 0; i < allCanvasElements.length; i++) {\n        assertCanvasIsIntegerSize(allCanvasElements[i])\n    }\n}\n"
  },
  {
    "path": "test/ci/Sidebar.ToggleSplitTest.ts",
    "content": "/**\n * Test script to validate sidebar split toggle behavior\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nconst getSidebarSplit = () => {\n    return document.querySelectorAll(\".sidebar-content\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Wait for sidebar split to appear\n    await oni.automation.waitFor(() => getSidebarSplit().length === 1)\n\n    // Validate sidebar is hidden\n    oni.commands.executeCommand(\"sidebar.toggle\")\n    await oni.automation.waitFor(() => getSidebarSplit().length === 0)\n    assert.ok(true, \"Sidebar was hidden.\")\n\n    // Validate sidebar comes back\n    oni.commands.executeCommand(\"sidebar.toggle\")\n    await oni.automation.waitFor(() => getSidebarSplit().length === 1)\n\n    assert.ok(true, \"Sidebar came back.\")\n}\n"
  },
  {
    "path": "test/ci/Snippets.BasicInsertTest.ts",
    "content": "/**\n * Simple snippet insert test case - validate the buffer is set, and that the cursor position is correct.\n * This is a very simple case w/o placeholders\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"ts\", oni)\n\n    await oni.snippets.insertSnippet(\"foo\")\n\n    const [firstLine] = await oni.editors.activeEditor.activeBuffer.getLines(0, 1)\n\n    assert.strictEqual(firstLine, \"foo\", \"Validate line is set correctly\")\n\n    // TODO: getCursorPosition should be added to API\n    const cursorPosition = await (oni.editors.activeEditor.activeBuffer as any).getCursorPosition()\n\n    assert.deepEqual(cursorPosition, { line: 0, character: 3 }, \"Validate cursor is at end of line\")\n}\n"
  },
  {
    "path": "test/ci/StatusBar-Mode.ts",
    "content": "/**\n * Test scripts for StatusBar\n *\n * Validating the 'mode' UX element showsu p\n */\n\nimport * as assert from \"assert\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { getElementByClassName } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    // Wait for completion popup to show\n    await oni.automation.waitFor(() => getElementByClassName(\"mode\") !== null)\n\n    // Check for 'alert' as an available completion\n    const statusBarModeElement = getElementByClassName(\"mode\")\n    const textContent = statusBarModeElement.textContent\n\n    assert.ok(\n        textContent.indexOf(\"normal\") >= 0,\n        \"Verify 'normal' was present in the statusbar mode item\",\n    )\n}\n"
  },
  {
    "path": "test/ci/TabBarSneakTest.ts",
    "content": "/**\n * Tab Bar Sneak Test\n *\n * This test ensures that a user can trigger the sneak functionality and\n * navigate to a different buffer\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\n\nimport {\n    createNewFile,\n    getElementByClassName,\n    getElementsBySelector,\n    getSingleElementBySelector,\n    getTemporaryFilePath,\n} from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Next, open a split in the current tab, and check the tab still remains dirty\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"e! buffer1\")\n    oni.automation.sendKeys(\"<enter>\")\n    await oni.automation.sleep(1500)\n\n    oni.automation.sendKeys(\":\")\n    oni.automation.sendKeys(\"e! buffer2\")\n    oni.automation.sendKeys(\"<enter>\")\n    await oni.automation.sleep(1500)\n\n    await oni.automation.sendKeys(\"<c-g>\")\n    await oni.automation.sleep(500)\n\n    const anyOni = oni as any\n    const sneak = anyOni.sneak.getSneakMatchingTag(\"buffer1\")\n    const keys: string = sneak.triggerKeys.toLowerCase()\n    await anyOni.automation.sendKeysV2(keys)\n    await oni.automation.sleep(2500)\n\n    const path = oni.editors.activeEditor.activeBuffer.filePath\n    assert.ok(path.includes(\"buffer1\"))\n}\n\nexport const settings = {\n    config: {\n        \"tabs.mode\": \"buffers\",\n        \"oni.loadInitVim\": false,\n    },\n    allowLogFailures: true,\n}\n"
  },
  {
    "path": "test/ci/TextmateHighlighting.DebugScopesTest.ts",
    "content": "/**\n * TextmateHighlighting.DebugScopesTest\n *\n * Validate the 'editor.textMateHighlighting.debugScopes' functionality\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { createNewFile, getElementByClassName } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Create typescript file with just \"window\" as teh contents\n    await createNewFile(\"ts\", oni, \"const test = 1;\")\n\n    // Grab the internal syntax highlight API, and check the token scopes\n    const currentBuffer = oni.editors.activeEditor.activeBuffer\n    const editorAsAny: any = oni.editors.activeEditor\n    const syntaxHighlighter = editorAsAny.syntaxHighlighter\n\n    let tokens = null\n    await oni.automation.waitFor(() => {\n        tokens = syntaxHighlighter.getHighlightTokenAt(\n            currentBuffer.id,\n            types.Position.create(0, 0),\n        )\n        return tokens && tokens.scopes && tokens.scopes.length > 0\n    }, 120000)\n\n    oni.automation.sendKeys(\"w\")\n\n    let element: HTMLElement = null\n    await oni.automation.waitFor(() => {\n        element = getElementByClassName(\"quick-info-debug-scopes\")\n        return !!element\n    }, 120000)\n\n    await oni.automation.waitFor(() => {\n        const items = element.getElementsByTagName(\"li\")\n        return items.length > 0\n    })\n\n    assert.ok(\n        element.textContent.indexOf(\"DEBUG: TextMate Scopes\") >= 0,\n        \"Validate debug scopes showed up\",\n    )\n}\n\nexport const settings = {\n    config: {\n        \"editor.textMateHighlighting.debugScopes\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/TextmateHighlighting.ScopesOnEnterTest.ts",
    "content": "/**\n * TextmateHighlighting.ScopesOnEnterTest\n *\n * Validate that syntax tokens for text mate highlighting are available on etner\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { createNewFile, getCompletionElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Create typescript file with just \"window\" as teh contents\n    await createNewFile(\"ts\", oni, \"window\")\n\n    // Grab the internal syntax highlight API, and check the token scopes\n    const currentBuffer = oni.editors.activeEditor.activeBuffer\n    const editorAsAny: any = oni.editors.activeEditor\n    const syntaxHighlighter = editorAsAny.syntaxHighlighter\n\n    let tokens = null\n    await oni.automation.waitFor(() => {\n        tokens = syntaxHighlighter.getHighlightTokenAt(\n            currentBuffer.id,\n            types.Position.create(0, 0),\n        )\n        return tokens && tokens.scopes && tokens.scopes.length > 0\n    }, 10000)\n\n    assert.deepEqual(\n        tokens.scopes,\n        [\"source.ts\", \"support.variable.dom.ts\"],\n        \"Validate the scopes are correct\",\n    )\n}\n\nexport const settings = {\n    config: {\n        \"experimental.editor.textMateHighlighting.enabled\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/TextmateHighlighting.TokenColorOverrideTest.ts",
    "content": "/**\n * TextmateHighlighting.ScopesOnEnterTest\n *\n * Validate that syntax tokens for text mate highlighting are available on etner\n */\n\nimport * as assert from \"assert\"\n\nimport * as Oni from \"oni-api\"\nimport * as types from \"vscode-languageserver-types\"\n\nimport { createNewFile, getCompletionElement } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Create typescript file with just \"window\" as teh contents\n    await createNewFile(\"ts\", oni, \"const test = 1;\")\n\n    // Grab the internal syntax highlight API, and check the token scopes\n    const currentBuffer = oni.editors.activeEditor.activeBuffer\n    const editorAsAny: any = oni.editors.activeEditor\n    const syntaxHighlighter = editorAsAny.syntaxHighlighter\n\n    let tokens = null\n    await oni.automation.waitFor(() => {\n        tokens = syntaxHighlighter.getHighlightTokenAt(\n            currentBuffer.id,\n            types.Position.create(0, 8),\n        )\n        return tokens && tokens.scopes && tokens.scopes.length > 0\n    }, 10000)\n\n    // Use an internal API to get the screen cell, and validate it is colored correctly\n    // Note that the position has to include the line numbers\n    const cell = editorAsAny._neovimEditor._screen.getCell(11 /*x, include line number */, 0)\n\n    // Validate the token color is correct\n    assert.strictEqual(cell.foregroundColor, \"#00ff00\")\n}\n\nexport const settings = {\n    config: {\n        \"editor.tokenColors\": [\n            {\n                scope: \"variable.other\",\n                settings: {\n                    foreground: \"#00FF00\",\n                },\n            },\n        ],\n    },\n}\n"
  },
  {
    "path": "test/ci/Theming.LightAndDarkColorsTest.ts",
    "content": "/**\n * Test script to validate themings are properly set for light/dark versions of theme\n */\n\nimport * as React from \"react\"\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nconst getBackgroundColor = (oni: Oni.Plugin.Api): string => {\n    return oni.colors.getColor(\"editor.background\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // TODO: Should we expose `request` as an API method?\n    const neovimAsAny: any = oni.editors.activeEditor.neovim\n\n    // Set theme to solarized light, validate background color\n    oni.configuration.setValues({ \"ui.colorscheme\": \"solarized8_light\" })\n    await oni.automation.waitFor(() => getBackgroundColor(oni) === \"#eee8d5\")\n\n    let background: string = await neovimAsAny.request(\"nvim_get_option\", [\"background\"])\n    assert.strictEqual(background, \"light\")\n\n    // Switch back to dark, validate the color was changed\n    oni.configuration.setValues({ \"ui.colorscheme\": \"solarized8_dark\" })\n    await oni.automation.waitFor(() => getBackgroundColor(oni) === \"#073642\")\n\n    background = await neovimAsAny.request(\"nvim_get_option\", [\"background\"])\n    assert.strictEqual(background, \"dark\")\n\n    // Switch back to light\n    oni.configuration.setValues({ \"ui.colorscheme\": \"solarized8_light\" })\n    await oni.automation.waitFor(() => getBackgroundColor(oni) === \"#eee8d5\")\n    background = await neovimAsAny.request(\"nvim_get_option\", [\"background\"])\n    assert.strictEqual(background, \"light\")\n\n    assert.ok(true, \"Color switches were successful!\")\n}\n"
  },
  {
    "path": "test/ci/Welcome.BufferLayerTest.ts",
    "content": "/**\n * Test script for the Welcome Screen Buffer Layer.\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\nimport { getSingleElementBySelector } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n    await oni.automation.sleep(2000)\n\n    const element = getSingleElementBySelector(\"[data-id='welcome-screen']\")\n\n    assert.ok(!!element, \"Validate the welcome screen is present\")\n\n    assert.ok(\n        oni.editors.activeEditor.activeBuffer.filePath.includes(\"WELCOME\"),\n        \"Validate that the current buffer is the Welcome one\",\n    )\n    oni.automation.sendKeys(\"<enter>\")\n    assert.ok(\n        !!oni.editors.activeEditor.activeBuffer.filePath,\n        \"Validate it opens empty unnamed new file\",\n    )\n}\n\nexport const settings = {\n    config: {\n        \"oni.useDefaultConfig\": true,\n        \"oni.loadInitVim\": false,\n        \"experimental.welcome.enabled\": true,\n        \"_internal.hasCheckedInitVim\": true,\n    },\n}\n"
  },
  {
    "path": "test/ci/WindowManager.ErrorBoundary.tsx",
    "content": "/**\n * Test script to verify per-workspace configuration settings\n */\n\nimport * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\n\nimport * as Oni from \"oni-api\"\n\nimport { createNewFile } from \"./Common\"\n\nexport class BadLayer implements Oni.BufferLayer {\n    public get id(): string {\n        return \"automation.test.layer\"\n    }\n\n    public render(context: Oni.BufferLayerRenderContext): JSX.Element {\n        throw new Error(\"Bad layer!\")\n    }\n}\n\nconst getErrorElements = () => {\n    return document.querySelectorAll(\".red-error-screen\")\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    await createNewFile(\"js\", oni)\n\n    oni.editors.activeEditor.activeBuffer.addLayer(new BadLayer())\n\n    // Wait for error screen to appear\n    await oni.automation.waitFor(() => getErrorElements().length === 1)\n\n    // Validate that some details about the error are shown\n    const errorElement = getErrorElements()[0]\n    const content = errorElement.textContent\n    assert.ok(content.indexOf(\"Bad layer\") >= 0)\n}\n\nexport const settings = {\n    allowLogFailures: true,\n}\n"
  },
  {
    "path": "test/ci/Workspace.ConfigurationTest.ts",
    "content": "/**\n * Test script to verify per-workspace configuration settings\n */\n\nimport * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\n\nimport * as Oni from \"oni-api\"\n\nimport { getTemporaryFolder } from \"./Common\"\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    await oni.automation.waitForEditors()\n\n    // Create workspace config\n    const temporaryFolder = getTemporaryFolder()\n    const oniConfigFolder = path.join(temporaryFolder, \".oni\")\n    mkdirp.sync(oniConfigFolder)\n\n    const oniConfigFile = path.join(oniConfigFolder, \"config.js\")\n    fs.writeFileSync(oniConfigFile, `module.exports = { \"citest.someConfig\": true }`)\n\n    const workspace = oni.workspace as any\n    workspace.changeDirectory(temporaryFolder)\n\n    // Once we've changed directory to that workspace, it should pick up the config value\n    oni.automation.waitFor(() => oni.configuration.getValue(\"citest.someConfig\"))\n}\n"
  },
  {
    "path": "test/ci/initVimPromptNotificationTest.ts",
    "content": "/**\n * initVimPromptNotification Test\n *\n * Validate that a notification is shown to the user if they have an init.vim\n * but are not using it\n */\n\n// import * as assert from \"assert\"\nimport { Assertor } from \"./Assert\"\n\nimport * as fs from \"fs\"\nimport * as Oni from \"oni-api\"\n\nimport {\n    createNewFile,\n    getElementByClassName,\n    getElementsBySelector,\n    getSingleElementBySelector,\n    getTemporaryFilePath,\n} from \"./Common\"\n\n// tslint:disable:no-console\n\nconst createAndReturnInitVimPath = (): string => {\n    const tempInitVim = getTemporaryFilePath(\"vim\")\n\n    console.log(\"- Writing init vim to: \" + tempInitVim)\n    fs.writeFileSync(tempInitVim, \"derpInvalidInitVimderp\")\n    console.log(\"- Write successful.\")\n\n    return tempInitVim\n}\n\nexport const test = async (oni: Oni.Plugin.Api) => {\n    const assert = new Assertor(\"Prompt Notification Test ===============\")\n    await oni.automation.waitForEditors()\n\n    await oni.automation.sleep(1500)\n    // Grab the notification element on startup\n    const notification = getSingleElementBySelector(\"[data-test='notification']\")\n    const notificationTitle = getSingleElementBySelector(\"[data-test='notification-title']\")\n\n    // Validate that the notification element appears\n    assert.defined(notification, \"Notification component exitsts\")\n    assert.defined(notificationTitle, \"Notification title exitsts\")\n\n    assert.assert(\n        notificationTitle.textContent.includes(\"init.vim\"),\n        \"Correct notification surfaces\",\n    )\n    ;(notification as HTMLElement).click()\n\n    await oni.automation.sleep(2500)\n\n    const isNotification = Boolean(getSingleElementBySelector(\"[data-test='notification']\"))\n    assert.assert(!isNotification, \"The notification disappears\")\n\n    const useInitVim = oni.configuration.getValue(\"oni.loadInitVim\")\n    assert.assert(!useInitVim, \"Init vim is disabled\")\n}\n\nexport const settings = {\n    env: {\n        MYVIMRC: createAndReturnInitVimPath(),\n    },\n    config: {\n        \"oni.loadInitVim\": false,\n        \"oni.useDefaultConfig\": true,\n        \"notifications.enabled\": true,\n        \"_internal.hasCheckedInitVim\": false,\n    },\n    allowLogFailures: true,\n}\n"
  },
  {
    "path": "test/collateral/1799_test.csv",
    "content": "1,3.56,7.6,\n1,0.437479,1,\n2,2.01333,4.6,\n2,0.556062,1,\n3,2.88,8.4,\n3,0.461792,0.95,\n4,2.76,8,\n4,0.446372,1,\n5,5.27333,13.6,\n5,0.280798,0.645,\n6,4.71333,9.8,\n6,0.296257,0.725,\n7,5.52667,14.2,\n7,0.274231,0.545,\n8,5.36667,10.4,\n8,0.288089,0.566667,\n9,6.68,12.8,\n9,0.235846,0.62,\n10,5.14667,11.6,\n10,0.287271,0.631667,\n11,5.67333,12.6,\n11,0.281639,0.649167,\n12,6.44667,13.8,\n12,0.235897,0.517619,\n13,8.34667,15.6,\n13,0.184609,0.485278,\n14,7.28,14.2,\n14,0.23081,0.419444,\n15,7.41333,13.6,\n15,0.218091,0.369683,\n16,6.7,18,\n16,0.242078,0.625,\n17,8.54667,19.2,\n17,0.204427,0.351753,\n18,8.29333,16.2,\n18,0.193528,0.426667,\n19,8.02,15.8,\n19,0.206042,0.417063,\n20,7.90667,12.6,\n20,0.212621,0.725,\n21,8.17333,17,\n21,0.204956,0.465278,\n22,8.45333,17.8,\n22,0.186504,0.323734,\n23,10.9733,19.6,\n23,0.169814,0.525,\n24,7.26,14.8,\n24,0.251678,0.866667,\n25,7.40667,13,\n25,0.261628,0.8,\n26,8.22667,18.4,\n26,0.221662,0.533333,\n27,7.26667,15.8,\n27,0.249828,0.6,\n28,6.97333,17.6,\n28,0.232787,0.581667,\n29,7.25333,18.2,\n29,0.227226,0.535,\n30,6.95333,14,\n30,0.245409,0.624167,\n31,6.24,11,\n31,0.248033,0.483333,\n32,5.83333,11.8,\n32,0.279263,0.75,\n33,6.71333,12.8,\n33,0.266427,0.525,\n34,6.34667,11.8,\n34,0.271922,0.558333,\n35,5.01333,10,\n35,0.293732,0.725,\n36,5.11333,11.8,\n36,0.312219,0.791667,\n37,5.12,12.6,\n37,0.316281,0.678333,\n38,5.34667,11.8,\n38,0.260828,0.506667,\n39,6.86667,11.2,\n39,0.220471,0.445952,\n40,6.62,12.2,\n40,0.271483,0.95,\n41,5.97333,13.2,\n41,0.286461,0.55,\n42,7.09333,13.2,\n42,0.273483,0.728333,\n43,6.38,11.6,\n43,0.246257,0.555,\n44,5.52,8.8,\n44,0.274789,0.592619,\n45,7.48667,13.8,\n45,0.216654,0.598333,\n46,7.10667,14.6,\n46,0.236483,0.45,\n47,7.56667,14.2,\n47,0.213285,0.507143,\n48,7.66667,14,\n48,0.22926,0.741667,\n49,6.76,14.6,\n49,0.251671,0.405952,\n50,8.23333,14.2,\n50,0.207992,0.436667,\n51,8.23333,18,\n51,0.207604,0.373688,\n52,9.12,18.8,\n52,0.189148,0.502183,\n53,8.24,14.4,\n53,0.213422,0.672619,\n54,7.96,13.8,\n54,0.202023,0.49797,\n55,6.92667,12.8,\n55,0.222603,0.666667,\n56,7.21333,14.2,\n56,0.224175,0.413004,\n57,6.49333,11.2,\n57,0.231747,0.450952,\n58,7.86667,16.6,\n58,0.233126,0.5,\n59,7.65333,12.2,\n59,0.210145,0.529524,\n60,7.4,13.6,\n60,0.248345,0.589286,\n61,6.62,12.8,\n61,0.268593,0.9,\n62,5.5,10,\n62,0.264681,0.62,\n63,5.9,10.8,\n63,0.255949,0.516667,\n64,4.57333,10,\n64,0.306798,0.633333,\n65,5.02667,11.8,\n65,0.279018,0.55,\n66,5.98667,16.8,\n66,0.26654,0.459524,\n67,6.46,11.6,\n67,0.239286,0.675,\n68,6.94667,12,\n68,0.216203,0.525,\n69,5.84667,11.2,\n69,0.27667,0.808333,\n70,5.59333,10,\n70,0.248311,0.575,\n71,5,11.6,\n71,0.294255,0.82,\n72,5.65333,15,\n72,0.246062,0.42873,\n73,5.69333,9.6,\n73,0.255842,0.5,\n74,5.23333,10,\n74,0.277885,0.5,\n75,5.31333,10.8,\n75,0.259098,0.509286,\n76,4.96667,12.8,\n76,0.315563,0.741667,\n77,4.82667,9.2,\n77,0.284719,0.516667,\n78,4.78,9,\n78,0.279943,0.57,\n79,5.55333,12,\n79,0.286593,0.683333,\n80,4.72667,12.6,\n80,0.319179,0.55,\n81,5.24667,9.6,\n81,0.271994,0.486667,\n82,5.12,9.8,\n82,0.285809,0.715,\n83,5.31333,9.6,\n83,0.277057,0.591667,\n84,4.22,7.6,\n84,0.319561,0.783333,\n85,5.15333,12.2,\n85,0.297029,0.716667,\n86,5.32,9.2,\n86,0.256556,0.565,\n87,4.82,8.2,\n87,0.300638,0.586667,\n88,5.53333,9,\n88,0.280971,0.586667,\n89,5.24667,8,\n89,0.280087,0.706667,\n90,4.72,8.4,\n90,0.322039,1,\n91,4.6,10.4,\n91,0.328339,0.75,\n92,4.66,7.8,\n92,0.3116,0.708333,\n93,4.82667,8.4,\n93,0.288199,0.55,\n94,5.13333,11.4,\n94,0.281016,0.758333,\n95,5.44667,11.6,\n95,0.273422,0.633333,\n96,5.6,10.8,\n96,0.270136,0.508333,\n97,5.42667,10.4,\n97,0.249028,0.583333,\n98,5.2,12,\n98,0.272311,0.6,\n99,5.08,10.6,\n99,0.292758,0.616667,\n100,4.72667,9.2,\n100,0.302949,0.816667,\n101,4.94,8.8,\n101,0.302402,0.7,\n102,4.74,9.6,\n102,0.30567,0.678333,\n103,4.71333,8.2,\n103,0.287449,0.625,\n104,4.79333,8.2,\n104,0.293909,0.595,\n105,4.94,10.2,\n105,0.305894,0.858333,\n106,3.72667,6.6,\n106,0.374727,1,\n107,5.11333,10.6,\n107,0.304057,0.95,\n108,4.34667,7.6,\n108,0.311004,0.725,\n109,4.12667,10.4,\n109,0.367855,0.733333,\n110,4.44,8.6,\n110,0.307033,0.7,\n111,3.88667,9.4,\n111,0.392197,1,\n112,4.01333,9.6,\n112,0.361028,0.786667,\n113,2.98667,7.2,\n113,0.411319,1,\n114,3.34667,6.6,\n114,0.372684,0.75,\n115,3.72,8.8,\n115,0.362311,0.75,\n116,3.02667,7.2,\n116,0.430723,0.833333,\n117,3.16,7.4,\n117,0.386036,0.85,\n118,4,7.6,\n118,0.365486,0.9,\n119,3.96667,8.6,\n119,0.309824,0.6,\n120,3.95333,7.2,\n120,0.341364,0.8,\n121,4.18,7.2,\n121,0.35319,1,\n122,4.58667,8.8,\n122,0.33784,0.933333,\n123,5.04667,10.6,\n123,0.293271,0.95,\n124,4.56667,8.4,\n124,0.347782,0.683333,\n125,4.1,10.4,\n125,0.347908,0.75,\n126,3.48667,6.2,\n126,0.375115,0.745,\n127,4.04,8,\n127,0.358374,1,\n128,4.70667,9.8,\n128,0.3093,0.496667,\n129,4.18667,7.2,\n129,0.331786,0.65,\n130,4.67333,9.8,\n130,0.311952,0.616667,\n131,3.86667,10.4,\n131,0.382656,1,\n132,3.65333,6.8,\n132,0.368136,0.783333,\n133,3.17333,6.6,\n133,0.378619,0.733333,\n134,3.27333,7.2,\n134,0.38668,0.633333,\n135,2.96667,10.2,\n135,0.394071,0.7,\n136,2.55333,6,\n136,0.428374,1,\n137,2.39333,5.6,\n137,0.476496,0.9,\n138,2.5,6.8,\n138,0.478398,1,\n139,2.83333,5.8,\n139,0.446835,0.95,\n140,2.85333,5.4,\n140,0.437873,0.833333,\n141,2.96667,6.4,\n141,0.41555,0.866667,\n142,3,5.8,\n142,0.40322,0.775,\n143,2.66667,6,\n143,0.437753,1,\n144,3.19333,6.4,\n144,0.360803,0.85,\n145,3.78,6,\n145,0.378538,0.9,\n146,3.28,6.2,\n146,0.385823,0.833333,\n147,3.97333,8.8,\n147,0.324668,0.8,\n148,3.27333,7.4,\n148,0.423303,1,\n149,3.59333,7.2,\n149,0.359974,0.786667,\n150,3.78667,8.8,\n150,0.355,0.766667,\n151,3.72,9,\n151,0.365976,0.72,\n152,3.23333,7.8,\n152,0.381853,1,\n153,3.00667,9.8,\n153,0.396634,0.9,\n154,3.25333,5.4,\n154,0.382357,0.9,\n155,3.15333,7.2,\n155,0.408502,0.85,\n156,2.96667,7.4,\n156,0.404416,0.608333,\n157,3.03333,6.2,\n157,0.403606,1,\n158,3.48667,6.8,\n158,0.378167,0.9,\n159,3.18667,5.2,\n159,0.408309,1,\n160,3.43333,6.2,\n160,0.360017,0.933333,\n161,3.18,5.8,\n161,0.370206,0.783333,\n162,2.68667,6.8,\n162,0.454603,0.9,\n163,3.5,7.2,\n163,0.395482,0.95,\n164,3.53333,7.6,\n164,0.391962,1,\n165,3.59333,7.2,\n165,0.326193,0.609286,\n166,3.16667,9.4,\n166,0.383808,0.7,\n167,2.90667,5.4,\n167,0.412875,1,\n168,2.82667,5.8,\n168,0.442714,1,\n169,3.02667,6.6,\n169,0.431233,0.9,\n170,3.22,8,\n170,0.410054,1,\n171,2.86,10.6,\n171,0.418323,0.733333,\n172,3.17333,7.2,\n172,0.420869,0.866667,\n173,2.58667,4.6,\n173,0.481949,0.95,\n174,3.08667,6.6,\n174,0.430833,0.883333,\n175,2.88667,8.2,\n175,0.407853,0.67,\n176,3,7.2,\n176,0.361067,0.666667,\n177,3.15333,6.8,\n177,0.428162,1,\n178,3.22667,7.2,\n178,0.387425,0.65,\n179,3.00667,6,\n179,0.435083,1,\n180,3.22667,6.2,\n180,0.39094,0.669286,\n181,3.24667,6.8,\n181,0.34618,0.95,\n182,3.02,6.2,\n182,0.395168,0.8,\n183,3.14,10,\n183,0.436698,1,\n184,3.31333,6,\n184,0.397328,0.708333,\n185,2.9,6.4,\n185,0.457281,0.833333,\n186,3.19333,6.6,\n186,0.398756,0.85,\n187,3.02667,6.8,\n187,0.452489,1,\n188,3.32667,7.4,\n188,0.356009,0.683333,\n189,4.74667,10.2,\n189,0.35515,0.85,\n190,3.94667,8.4,\n190,0.350732,0.85,\n191,3.74,8.6,\n191,0.377041,1,\n192,3.76,10,\n192,0.406397,1,\n193,2.65333,5.8,\n193,0.452024,0.875,\n194,3.11333,6.8,\n194,0.376443,0.8,\n195,3.65333,6.6,\n195,0.348553,0.7,\n196,3.14667,6.6,\n196,0.385144,0.7,\n197,3.28667,7.4,\n197,0.412232,1,\n198,2.62667,5.6,\n198,0.434051,0.733333,\n199,3.42,7.2,\n199,0.365274,0.833333,\n200,2.88,7.2,\n200,0.439313,0.85,\n201,2.62,6.6,\n201,0.476487,1,\n202,2.86,4.6,\n202,0.432699,0.95,\n203,2.02,6.4,\n203,0.510843,0.85,\n204,2.54,6.6,\n204,0.448921,0.9,\n205,2.31333,4.8,\n205,0.477862,1,\n206,2.2,5.2,\n206,0.477254,1,\n207,2.38,4.4,\n207,0.474934,1,\n208,2.5,5.2,\n208,0.450849,1,\n209,2.32,6.8,\n209,0.49025,1,\n210,2.98667,7.2,\n210,0.450824,1,\n211,1.58,4.8,\n211,0.569626,1,\n212,2.08,4.6,\n212,0.473307,1,\n213,1.83333,4.2,\n213,0.5322,1,\n214,1.76,5.2,\n214,0.550118,1,\n215,2.38667,5.6,\n215,0.457676,1,\n216,1.89333,4.2,\n216,0.495914,0.9,\n217,2.17333,4.4,\n217,0.505963,1,\n218,2,6.2,\n218,0.492369,1,\n219,1.77333,5.2,\n219,0.57552,1,\n220,1.85333,6.4,\n220,0.544561,1,\n221,1.67333,4.4,\n221,0.556647,1,\n222,2.12667,6,\n222,0.482696,0.8,\n223,1.78667,8,\n223,0.51463,1,\n224,2.05333,4.6,\n224,0.484586,1,\n225,1.62,5.8,\n225,0.564434,1,\n226,2.36,6.6,\n226,0.441575,0.808333,\n227,2.35333,5.8,\n227,0.472114,0.85,\n228,2.47333,6.6,\n228,0.45433,0.8,\n229,2.38,6.2,\n229,0.456567,0.8,\n230,2.74,5.2,\n230,0.43338,0.95,\n231,2.20667,4.8,\n231,0.494491,1,\n232,2.24667,6.4,\n232,0.507431,1,\n233,2.71333,5.8,\n233,0.43178,1,\n234,2.54,5,\n234,0.445999,1,\n235,2.48,5.4,\n235,0.455501,0.866667,\n236,2.48667,6.6,\n236,0.427155,0.816667,\n237,2.55333,5,\n237,0.465761,1,\n238,2.12,6.4,\n238,0.532746,1,\n239,2.79333,6.2,\n239,0.444151,0.9,\n240,2.94,8.2,\n240,0.440119,0.9,\n241,3.49333,7.2,\n241,0.353381,0.866667,\n242,2.96667,5.4,\n242,0.441822,0.85,\n243,2.5,6.4,\n243,0.457864,1,\n244,2.28,5.6,\n244,0.451565,0.816667,\n245,2.52,6.8,\n245,0.497781,1,\n246,2.82,7.2,\n246,0.418527,1,\n247,2.48667,4.8,\n247,0.470282,1,\n248,2.34667,5.2,\n248,0.50958,1,\n249,2.48667,6.8,\n249,0.460036,1,\n250,2.64667,6.4,\n250,0.468095,0.9,\n251,2.67333,7.2,\n251,0.428213,1,\n252,2.58667,6,\n252,0.416967,0.8,\n253,2.58,7.2,\n253,0.415703,0.8,\n254,2.9,5.8,\n254,0.431563,0.95,\n255,2.66667,6.4,\n255,0.459547,1,\n256,3.36667,9.2,\n256,0.402384,1,\n257,2.24,7.2,\n257,0.473094,1,\n258,1.86667,4.4,\n258,0.508819,1,\n259,2.23333,5,\n259,0.51177,0.95,\n260,2.6,5.2,\n260,0.435044,0.825,\n261,2.22667,5.2,\n261,0.488627,1,\n262,2.1,4.2,\n262,0.505553,1,\n263,1.68667,4,\n263,0.586556,1,\n264,1.97333,4.8,\n264,0.494275,1,\n265,2.20667,5.4,\n265,0.476238,1,\n266,2.01333,5,\n266,0.508254,1,\n267,1.96,5,\n267,0.477627,0.9,\n268,1.88667,3.8,\n268,0.540661,1,\n269,2.26,6.4,\n269,0.47675,1,\n270,2.23333,6.2,\n270,0.460628,0.9,\n271,2.68667,5.8,\n271,0.459677,1,\n272,2.66,5.2,\n272,0.454491,1,\n273,1.92,4.2,\n273,0.50806,0.825,\n274,2.16667,5.6,\n274,0.505524,1,\n275,2.48,4.8,\n275,0.47306,1,\n276,2.44667,5.2,\n276,0.476215,0.9,\n277,2.34667,5,\n277,0.463112,0.9,\n278,2.47333,6.8,\n278,0.460455,0.95,\n279,2.31333,4.2,\n279,0.478176,0.9,\n280,1.96,4.6,\n280,0.512976,1,\n281,1.76,4.6,\n281,0.547976,1,\n282,1.62,4,\n282,0.537529,1,\n283,1.84667,5,\n283,0.539841,1,\n284,1.30667,3.4,\n284,0.650721,1,\n285,1.80667,4,\n285,0.501992,0.866667,\n286,1.30667,5.4,\n286,0.605444,1,\n287,1.64667,3.4,\n287,0.545159,0.85,\n288,1.89333,4.6,\n288,0.54145,1,\n289,1.18,3.2,\n289,0.649013,1,\n290,1.88667,4.2,\n290,0.53027,0.95,\n291,1.82,6.2,\n291,0.560853,1,\n292,2.62667,7,\n292,0.436557,1,\n293,2.68,8.6,\n293,0.437837,1,\n294,2.74,7,\n294,0.405694,0.75,\n295,2.79333,6.8,\n295,0.437383,1,\n296,2.71333,5.8,\n296,0.442146,1,\n297,2.21333,4.6,\n297,0.469976,1,\n298,2.39333,5.4,\n298,0.465377,1,\n299,1.88667,4.2,\n299,0.525036,1,\n300,2.4,5.2,\n300,0.466634,0.883333,\n301,2.66667,7.4,\n301,0.434603,0.933333,\n302,1.87333,5,\n302,0.5017,1,\n303,2.11333,5.4,\n303,0.559308,0.95,\n304,1.92667,4.6,\n304,0.5372,0.95,\n305,2.85333,7.2,\n305,0.410869,1,\n306,2.66667,5.8,\n306,0.465849,0.9,\n307,2.02,5.2,\n307,0.531366,1,\n308,2.57333,4.8,\n308,0.450706,0.85,\n309,2.40667,4.6,\n309,0.466124,0.95,\n310,2.52,6,\n310,0.475831,1,\n311,2.18667,6,\n311,0.466435,0.85,\n312,2.18667,7.6,\n312,0.472294,1,\n313,1.95333,5.4,\n313,0.514694,1,\n314,1.74667,4.8,\n314,0.579004,1,\n315,2.31333,5,\n315,0.476296,1,\n316,1.94,4.2,\n316,0.473369,0.8,\n317,2.3,6.2,\n317,0.462818,1,\n318,2.28,6.2,\n318,0.483497,1,\n319,2.56667,5.4,\n319,0.448443,1,\n320,2.52,6.2,\n320,0.422349,0.75,\n321,2.18,6.2,\n321,0.47977,0.883333,\n322,2.08667,5.6,\n322,0.465219,0.75,\n323,2.42,5.8,\n323,0.466985,1,\n324,1.78667,7,\n324,0.567405,1,\n325,2.03333,5.4,\n325,0.506673,1,\n326,2.08,4.6,\n326,0.477757,0.85,\n327,2.63333,7,\n327,0.471682,1,\n328,2.66667,5.8,\n328,0.442217,1,\n329,2.32,5.2,\n329,0.47054,1,\n330,2.03333,5.6,\n330,0.478944,0.875,\n331,2.01333,5.2,\n331,0.501564,0.8,\n332,2.28667,6,\n332,0.472452,1,\n333,2.41333,5.4,\n333,0.470693,0.808333,\n334,1.89333,4.2,\n334,0.543032,0.95,\n335,2.52667,8.8,\n335,0.435543,1,\n336,2.36667,4.4,\n336,0.445442,0.85,\n337,2.2,6,\n337,0.478804,1,\n338,2.2,4.2,\n338,0.518295,1,\n339,1.75333,3.6,\n339,0.555188,1,\n340,2.66667,6,\n340,0.409008,0.85,\n341,2.4,6,\n341,0.454118,0.825,\n342,2.92667,8.6,\n342,0.461668,0.883333,\n343,2.16667,5.6,\n343,0.511685,0.85,\n344,3.12667,5.2,\n344,0.388558,0.766667,\n345,2.52667,6.2,\n345,0.433047,0.716667,\n346,2.6,5.8,\n346,0.470701,1,\n347,2.47333,5.6,\n347,0.441511,1,\n348,2.68667,5.8,\n348,0.420033,0.8,\n349,2.86667,6.4,\n349,0.435031,1,\n350,2.11333,6,\n350,0.484766,1,\n351,2.19333,4.4,\n351,0.510548,1,\n352,2.14667,4.4,\n352,0.506132,1,\n353,2.47333,5.8,\n353,0.454013,1,\n354,2.51333,6.4,\n354,0.448807,0.8,\n355,3.14667,7.4,\n355,0.392087,0.75,\n356,2.66,4.4,\n356,0.432419,1,\n357,2.49333,6.2,\n357,0.433544,0.8,\n358,2.84,6.8,\n358,0.3895,0.803333,\n359,2.95333,8.2,\n359,0.429844,1,\n360,2.58667,7.4,\n360,0.449982,1,\n361,2.45333,5.6,\n361,0.457304,1,\n362,1.88,4.6,\n362,0.509452,1,\n363,2.24,5.4,\n363,0.480854,1,\n364,2.13333,5,\n364,0.472249,1,\n365,2.20667,5,\n365,0.459313,1,\n366,2.52,4,\n366,0.454307,0.85,\n367,2.03333,4.4,\n367,0.520156,1,\n368,2.44,6,\n368,0.477072,1,\n369,1.85333,3.2,\n369,0.542495,1,\n370,1.7,3.4,\n370,0.552321,1,\n371,1.84,4,\n371,0.492238,1,\n372,2.39333,7,\n372,0.427948,0.9,\n373,2.2,5.2,\n373,0.444897,0.7,\n374,2.34667,5.4,\n374,0.472208,0.95,\n375,2.20667,4.4,\n375,0.489942,1,\n376,2.96,5.8,\n376,0.462368,1,\n377,2.96,6.4,\n377,0.420054,0.8,\n378,2.26667,5.6,\n378,0.489559,1,\n379,1.64667,4.2,\n379,0.57521,1,\n380,2.16,4,\n380,0.480578,1,\n381,1.86,4.2,\n381,0.526992,1,\n382,1.72,5.2,\n382,0.531216,0.9,\n383,2.07333,5.4,\n383,0.501423,0.9,\n384,1.89333,4.2,\n384,0.531581,1,\n385,2.11333,4.8,\n385,0.543045,1,\n386,2.10667,7.6,\n386,0.50893,1,\n387,1.52667,5.4,\n387,0.569365,1,\n388,1.78667,4.2,\n388,0.536425,1,\n389,2.09333,5,\n389,0.489098,0.816667,\n390,1.57333,4.8,\n390,0.560436,1,\n391,1.88667,4.6,\n391,0.575503,1,\n392,1.81333,4.2,\n392,0.570767,1,\n393,1.64,4.8,\n393,0.553587,1,\n394,1.89333,3.8,\n394,0.531174,1,\n395,2.51333,4.8,\n395,0.447224,1,\n396,2.90667,6.6,\n396,0.430376,1,\n397,1.76,4.6,\n397,0.538901,0.833333,\n398,2.04667,4.4,\n398,0.469312,0.733333,\n399,1.96,5,\n399,0.531673,1,\n400,1.88,3.8,\n400,0.51723,1,\n401,2.08,6,\n401,0.510847,1,\n402,2.10667,6.6,\n402,0.510274,1,\n403,2.54,5.2,\n403,0.461669,1,\n404,1.9,3.6,\n404,0.519275,1,\n405,1.82,4.4,\n405,0.534647,1,\n406,2.08,4.4,\n406,0.531114,1,\n407,2.24667,4.6,\n407,0.501163,1,\n408,2.04667,5,\n408,0.498242,1,\n409,1.98,4.6,\n409,0.511336,1,\n410,1.98667,6.6,\n410,0.537108,1,\n411,1.76667,4.6,\n411,0.54296,1,\n412,1.72667,5.2,\n412,0.53546,0.9,\n413,1.92667,4.6,\n413,0.523562,1,\n414,2.15333,5.8,\n414,0.451976,1,\n415,2,5.2,\n415,0.524427,1,\n416,1.8,3.8,\n416,0.511282,0.816667,\n417,1.70667,4.6,\n417,0.516452,0.9,\n418,1.88,5.4,\n418,0.539151,1,\n419,1.52667,3,\n419,0.577317,1,\n420,1.64,5,\n420,0.554984,0.9,\n421,1.84,4,\n421,0.531123,1,\n422,1.92667,4.8,\n422,0.51155,0.95,\n423,1.89333,3.2,\n423,0.500567,0.85,\n424,1.46,4,\n424,0.59404,1,\n425,1.77333,4.2,\n425,0.504667,0.9,\n426,2.19333,4.8,\n426,0.454251,1,\n427,2.08,7,\n427,0.485558,1,\n428,2.00667,6.8,\n428,0.50327,1,\n429,1.9,3.8,\n429,0.505079,1,\n430,1.56,4.2,\n430,0.56872,1,\n431,1.9,5.4,\n431,0.515466,0.85,\n432,2.30667,5.6,\n432,0.504082,1,\n433,2.10667,6,\n433,0.473795,0.95,\n434,1.74,6.6,\n434,0.539929,1,\n435,1.28667,4.2,\n435,0.621706,1,\n436,1.71333,4.8,\n436,0.513167,1,\n437,1.61333,3.6,\n437,0.586964,1,\n438,1.75333,4.6,\n438,0.602011,1,\n439,1.46,3.2,\n439,0.595857,1,\n440,1.66667,3.8,\n440,0.52723,1,\n441,1.53333,4.2,\n441,0.555111,1,\n442,1.2,4,\n442,0.680143,1,\n443,1.59333,3.4,\n443,0.57381,1,\n444,1.44,4.4,\n444,0.588111,1,\n445,1.4,3.6,\n445,0.593389,1,\n446,1.51333,4.2,\n446,0.569651,1,\n447,1.59333,5.4,\n447,0.574603,1,\n448,1.66,4.6,\n448,0.558484,1,\n449,1.42,4.4,\n449,0.581841,0.9,\n450,1.81333,5.2,\n450,0.501492,1,\n451,1.53333,4.2,\n451,0.57421,1,\n452,1.84667,4.6,\n452,0.529425,1,\n453,1.88667,4.2,\n453,0.502865,0.95,\n454,1.9,6.6,\n454,0.499553,1,\n455,1.38667,4.2,\n455,0.587456,1,\n456,1.84667,4.6,\n456,0.516654,1,\n457,1.5,4.2,\n457,0.59146,1,\n458,1.26,5.2,\n458,0.627722,1,\n459,2,5.4,\n459,0.485271,0.9,\n460,1.96,5,\n460,0.51132,1,\n461,2.05333,7.4,\n461,0.455008,0.766667,\n462,1.37333,3.8,\n462,0.59554,1,\n463,1.44667,3.2,\n463,0.608948,1,\n464,1.65333,3.8,\n464,0.587135,1,\n465,1.50667,3.4,\n465,0.559452,1,\n466,1.34667,3.8,\n466,0.593143,1,\n467,1.44,6.8,\n467,0.599717,1,\n468,1.64,5.8,\n468,0.555595,1,\n469,1.88,5.6,\n469,0.543012,1,\n470,2.06667,4.6,\n470,0.48775,1,\n471,1.88,4.4,\n471,0.53398,1,\n472,1.91333,5.2,\n472,0.515985,0.95,\n473,1.67333,3.8,\n473,0.533299,1,\n474,1.37333,4.2,\n474,0.620619,1,\n475,1.86667,5.6,\n475,0.532314,1,\n476,1.67333,3.8,\n476,0.559119,1,\n477,1.81333,4.2,\n477,0.545632,1,\n478,1.38,3.2,\n478,0.616698,1,\n479,1.60667,4.4,\n479,0.564484,1,\n480,1.73333,4.4,\n480,0.521294,0.9,\n481,2.48667,5.4,\n481,0.447148,1,\n482,2.39333,6.2,\n482,0.457094,0.95,\n483,1.92,4,\n483,0.543395,1,\n484,2.18667,5.4,\n484,0.512933,1,\n485,2.13333,4,\n485,0.456008,1,\n486,2.02,5.6,\n486,0.49341,1,\n487,1.91333,4.4,\n487,0.529228,1,\n488,1.82,5,\n488,0.516655,1,\n489,1.61333,4,\n489,0.579714,1,\n490,1.84667,5.4,\n490,0.532148,1,\n491,1.69333,4.2,\n491,0.549004,1,\n492,1.97333,5.4,\n492,0.524544,0.9,\n493,1.85333,3.8,\n493,0.542805,1,\n494,2.01333,4.6,\n494,0.472156,0.866667,\n495,1.8,4.4,\n495,0.493091,0.9,\n496,2.02667,5.6,\n496,0.463537,1,\n497,1.66667,3.6,\n497,0.543938,1,\n498,1.78667,7,\n498,0.501791,1,\n499,1.78667,4.2,\n499,0.476944,0.9,\n500,1.46667,4.2,\n500,0.608456,1,"
  },
  {
    "path": "test/common/Oni.ts",
    "content": "import * as assert from \"assert\"\nimport * as path from \"path\"\n\nimport { Application } from \"spectron\"\n\nimport { ensureProcessNotRunning } from \"./ensureProcessNotRunning\"\n\nconst log = (msg: string) => {\n    console.log(msg) // tslint:disable-line no-console\n}\n\nconst isCiBuild = () => {\n    const ciBuild = !!(\n        process.env.ONI_AUTOMATION_USE_DIST_BUILD ||\n        process.env.CONTINUOUS_INTEGRATION /* set by travis */ ||\n        process.env.APPVEYOR\n    ) /* set by appveyor */\n    log(\"isCiBuild: \" + ciBuild)\n    return ciBuild\n}\n\nconst getWindowsExecutablePathOnCiMachine = () => {\n    switch (process.env.PLATFORM) {\n        case \"x86\":\n            return path.join(__dirname, \"..\", \"..\", \"..\", \"dist\", \"win-ia32-unpacked\", \"Oni.exe\")\n        case \"x64\":\n            return path.join(__dirname, \"..\", \"..\", \"..\", \"dist\", \"win-unpacked\", \"Oni.exe\")\n        default:\n            throw new Error(`Unable to find Oni executable for Windows arch ${process.arch}`)\n    }\n}\n\nconst getExecutablePathOnCiMachine = () => {\n    switch (process.platform) {\n        case \"win32\":\n            return getWindowsExecutablePathOnCiMachine()\n        case \"darwin\":\n            return path.join(\n                __dirname,\n                \"..\",\n                \"..\",\n                \"..\",\n                \"dist\",\n                \"mac\",\n                \"Oni.app\",\n                \"Contents\",\n                \"MacOS\",\n                \"Oni\",\n            )\n        case \"linux\":\n            const archFlag = process.arch === \"x64\" ? \"\" : \"ia32-\"\n            return path.join(\n                __dirname,\n                \"..\",\n                \"..\",\n                \"..\",\n                \"dist\",\n                `linux-${archFlag}unpacked`,\n                \"oni\",\n            )\n        default:\n            throw new Error(`Unable to find Oni executable for platform ${process.platform}`)\n    }\n}\n\nconst getExecutablePathLocally = () => {\n    const nodeModulesBinPath = path.join(__dirname, \"..\", \"..\", \"..\", \"node_modules\", \".bin\")\n    return process.platform === \"win32\"\n        ? path.join(nodeModulesBinPath, \"electron.cmd\")\n        : path.join(nodeModulesBinPath, \"electron\")\n}\n\nconst getArgsForCiMachine = () => []\nconst getArgsForLocalExecution = () => [\n    path.join(__dirname, \"..\", \"..\", \"..\", \"lib\", \"main\", \"src\", \"main.js\"),\n]\n\nexport interface OniStartOptions {\n    env?: {\n        ONI_CONFIG_FILE?: string\n        MYVIMRC?: string\n        [key: string]: string\n    }\n}\n\nexport class Oni {\n    private _app: Application\n\n    public get client(): any {\n        return this._app.client\n    }\n\n    public async start(options: OniStartOptions = {}): Promise<void> {\n        const ciBuild = isCiBuild()\n        const executablePath = ciBuild ? getExecutablePathOnCiMachine() : getExecutablePathLocally()\n        const executableArgs = ciBuild ? getArgsForCiMachine() : getArgsForLocalExecution()\n        log(\"Using executable path: \" + executablePath)\n        log(\"Using executable args: \" + executableArgs)\n\n        log(\"Start options: \" + JSON.stringify(options))\n\n        this._app = new Application({\n            path: executablePath,\n            args: executableArgs,\n            env: options.env,\n        })\n\n        log(\"Oni starting...\")\n        await this._app.start()\n        log(\"Oni started. Waiting for window load..\")\n        await this.client.waitUntilWindowLoaded()\n        const count = await this.client.getWindowCount()\n        assert.ok(count > 0)\n\n        log(`Window loaded. Reports ${count} windows.`)\n    }\n\n    public async close(): Promise<void> {\n        log(\"Closing Oni...\")\n        const windowCount = await Promise.race([\n            this.client.getWindowCount(),\n            new Promise(resolve => {\n                setTimeout(() => {\n                    resolve(\"Timed out waiting for window count\")\n                }, 1000)\n            }),\n        ])\n        log(`- current window count: ${windowCount}`)\n        if (this._app) {\n            let attempts = 1\n            while (attempts < 5) {\n                if (!this._app.isRunning()) {\n                    log(\"- _app.isRunning() is now false\")\n                    break\n                }\n\n                log(\"- Calling _app.stop\")\n                let didStop = false\n                const promise1 = this._app.stop().then(\n                    () => {\n                        log(\"_app.stop promise completed!\")\n                        didStop = true\n                    },\n                    err => {\n                        // tslint:disable-next-line\n                        console.error(err)\n                    },\n                )\n\n                const promise2 = sleep(15000)\n\n                log(\"- Racing with 15s timer...\")\n                const race = Promise.race([promise1, promise2])\n                await race\n\n                log(\"- Race complete. didStop: \" + didStop)\n\n                if (!didStop) {\n                    log(\"- Attempting to force close processes:\")\n                    await ensureProcessNotRunning(\"nvim\")\n                    await ensureProcessNotRunning(\"oni\")\n                    await ensureProcessNotRunning(\"chromedriver\")\n                    log(\"- Force close complete\")\n                }\n\n                attempts++\n            }\n        }\n        log(\"Oni closed.\")\n    }\n}\n\nconst sleep = (timeout: number = 1000) => {\n    return new Promise(resolve => {\n        setTimeout(resolve, timeout)\n    })\n}\n"
  },
  {
    "path": "test/common/ensureProcessNotRunning.ts",
    "content": "import * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport { Oni } from \"./Oni\"\n//\n// tslint:disable:no-console\n\nconst findProcess = require(\"find-process\") // tslint:disable-line\n\n// Sometimes, on the automation machines, Oni will still be running\n// when starting the test. It will fail if there is an existing instance\n// running, so we need to make sure to finish it.\nexport const ensureProcessNotRunning = async (processName: string) => {\n    let attempts = 1\n    const maxAttempts = 5\n\n    while (attempts < maxAttempts) {\n        console.log(`${attempts}/${maxAttempts} Active Processes:`)\n\n        const targetProcessGone = await tryToKillProcess(processName)\n\n        if (targetProcessGone) {\n            console.log(`All ${processName} processes gone!`)\n            return\n        }\n\n        attempts++\n    }\n}\n\nconst tryToKillProcess = async (processName: string): Promise<boolean> => {\n    const targetProcesses = await findProcess(\"name\", processName)\n\n    targetProcesses.forEach(processInfo => {\n        console.log(` - Name: ${processInfo.name} PID: ${processInfo.pid}`)\n    })\n\n    const isValidTargetProcess = processInfo =>\n        processInfo.name.toLowerCase().indexOf(processName) >= 0\n    const filteredProcesses = targetProcesses.filter(isValidTargetProcess)\n\n    console.log(`- Found ${filteredProcesses.length} processes with name:  ${processName}`)\n\n    if (filteredProcesses.length === 0) {\n        console.log(`No ${processName} processes found - leaving.`)\n        return true\n    }\n\n    filteredProcesses.forEach(processInfo => {\n        console.log(\"Attempting to kill pid: \" + processInfo.pid)\n        // Sometimes, there can be a race condition here. For example,\n        // the process may have closed between when we queried above\n        // and when we try to kill it. So we'll wrap it in a try/catch.\n        try {\n            process.kill(processInfo.pid)\n        } catch (ex) {\n            console.warn(ex)\n        }\n    })\n\n    return false\n}\n"
  },
  {
    "path": "test/common/index.ts",
    "content": "export * from \"./Oni\"\nexport * from \"./runInProcTest\"\n"
  },
  {
    "path": "test/common/runInProcTest.ts",
    "content": "import * as assert from \"assert\"\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nimport { Oni } from \"./Oni\"\n\nimport { ensureProcessNotRunning } from \"./ensureProcessNotRunning\"\n\n// tslint:disable:no-console\n\nexport interface ITestCase {\n    name: string\n    testPath: string\n    allowLogFailures: boolean\n    env: {\n        [key: string]: string\n    }\n}\n\nexport interface IFailedTest {\n    test: string\n    path: string\n    expected: any\n    actual: any\n}\n\nconst normalizePath = p => p.split(\"\\\\\").join(\"/\")\n\nconst loadTest = (rootPath: string, testName: string): ITestCase => {\n    const testPath = path.join(rootPath, testName + \".js\")\n\n    const testMeta = require(testPath)\n    const testDescription = testMeta.settings || {}\n\n    const normalizedMeta: ITestCase = {\n        name: testDescription.name || testName,\n        testPath: normalizePath(testPath),\n        allowLogFailures: testDescription.allowLogFailures,\n        env: {\n            ...(testDescription.env || {}),\n            ONI_CONFIG_FILE: getConfigPath(testMeta.settings, rootPath),\n        },\n    }\n\n    return normalizedMeta\n}\n\nimport * as os from \"os\"\n\nconst getConfigPath = (settings: any, rootPath: string) => {\n    settings = settings || {}\n\n    if (settings.configPath) {\n        if (!path.isAbsolute(settings.configPath)) {\n            return normalizePath(path.join(rootPath, settings.configPath))\n        } else {\n            return settings.configPath\n        }\n    } else if (settings.config) {\n        return normalizePath(serializeConfig(settings.config))\n    } else {\n        // Fix #1436 - if no config is specified, we'll just use\n        // the empty config, so that the user's config doesn't\n        // impact the test results.\n        return normalizePath(serializeConfig({ \"oni.loadInitVim\": false }))\n    }\n}\n\n// Helper method to write a config to a temporary folder\n// Returns the path to the serialized config\nconst serializeConfig = (configValues: { [key: string]: any }): string => {\n    const stringifiedConfig = Object.keys(configValues).map(key => {\n        return `\"${key}\": ${JSON.stringify(configValues[key])},`\n    })\n\n    const outputConfig = `// User Configuration${os.EOL}${os.EOL}module.exports = {${\n        os.EOL\n    }${stringifiedConfig.join(os.EOL)}${os.EOL}}`\n\n    const folder = os.tmpdir()\n    const fileName = \"config_\" + new Date().getTime().toString() + \".js\"\n\n    const fullFilepath = path.join(folder, fileName)\n    console.log(\"Writing config to: \" + fullFilepath)\n    console.log(\"Config contents: \" + outputConfig)\n    fs.writeFileSync(fullFilepath, outputConfig)\n    return fullFilepath\n}\n\nconst startTime = new Date().getTime()\n\nconst logWithTimeStamp = (message: string) => {\n    const currentTime = new Date().getTime()\n    const delta = currentTime - startTime\n    const deltaInSeconds = delta / 1000\n\n    console.log(`[${deltaInSeconds}] ${message}`)\n}\n\nexport const runInProcTest = (\n    rootPath: string,\n    testName: string,\n    timeout: number = 5000,\n    failures: IFailedTest[] = null,\n) => {\n    // tslint:disable-next-line\n    describe(testName, function() {\n        // TODO: See if we can remove this to stabilize tests.\n        this.retries(2)\n\n        let testCase: ITestCase\n        let oni: Oni\n\n        it(\"ci test: \" + testName, async () => {\n            try {\n                logWithTimeStamp(\"TEST: \" + testName)\n                testCase = loadTest(rootPath, testName)\n                const startOptions = {\n                    env: testCase.env,\n                }\n                oni = new Oni()\n\n                logWithTimeStamp(\"Calling oni.start\")\n                await oni.start(startOptions)\n                logWithTimeStamp(\"Completed oni.start\")\n\n                console.log(\"Waiting for editor element...\")\n                await oni.client.waitForExist(\".editor\", timeout)\n\n                logWithTimeStamp(\"Found editor element. Getting editor element text: \")\n                const text = await oni.client.getText(\".editor\")\n                logWithTimeStamp(\"Editor element text: \" + text)\n\n                logWithTimeStamp(\"Test path: \" + testCase.testPath) // tslint:disable-line\n\n                oni.client.execute(\"Oni.automation.runTest('\" + testCase.testPath + \"')\")\n\n                logWithTimeStamp(\"Waiting for result...\") // tslint:disable-line\n                const value = await oni.client.waitForExist(\".automated-test-result\", 120000)\n                logWithTimeStamp(\"waitForExist for 'automated-test-result' complete: \" + value)\n\n                console.log(\"Retrieving logs...\")\n\n                const isLogFailure = (log: any) =>\n                    log.level === \"SEVERE\" && !testCase.allowLogFailures\n                const anyLogFailure = (logs: any[]) => logs.filter(isLogFailure).length > 0\n\n                const writeLogs = (logs: any[], forceWrite?: boolean): void => {\n                    const anyFailures = anyLogFailure(logs)\n                    const shouldWrite = !result || !result.passed || anyFailures || forceWrite\n\n                    logs.forEach(log => {\n                        const logMessage = `[${log.level}] ${log.message}`\n\n                        if (shouldWrite) {\n                            console.log(logMessage)\n                        }\n\n                        if (isLogFailure(log)) {\n                            assert.ok(false, logMessage)\n                        }\n                    })\n\n                    if (!shouldWrite) {\n                        console.log(\"Skipping log output since test passed.\")\n                    }\n                }\n\n                console.log(\"Getting result...\")\n                const resultText = await oni.client.getText(\".automated-test-result\")\n                const result = JSON.parse(resultText)\n\n                const rendererLogs: any[] = await oni.client.getRenderProcessLogs()\n                console.log(\"\")\n                console.log(\"---LOGS (Renderer): \" + testName)\n                writeLogs(rendererLogs)\n                console.log(\"--- \" + testName + \" ---\")\n\n                console.log(\"---LOGS (Main): \" + testName)\n                if (!result.passed) {\n                    const mainProcessLogs: any[] = await oni.client.getMainProcessLogs()\n                    mainProcessLogs.forEach(l => {\n                        console.log(l)\n                    })\n                } else {\n                    console.log(\"Skipping log output since test passed.\")\n                }\n                console.log(\"--- \" + testName + \" ---\")\n\n                console.log(\"\")\n                logWithTimeStamp(\"---RESULT: \" + testName)\n                console.log(resultText) // tslint:disable-line\n                console.log(\"--- \" + testName + \" ---\")\n                console.log(\"\")\n\n                if (failures && !result.passed) {\n                    const failedTest: IFailedTest = {\n                        test: testName,\n                        path: testCase.testPath,\n                        expected: result.exception.expected,\n                        actual: result.exception.actual,\n                    }\n                    failures.push(failedTest)\n                }\n\n                assert.ok(result.passed)\n            } finally {\n                try {\n                    logWithTimeStamp(\"Calling oni.close...\")\n                    await oni.close()\n                    logWithTimeStamp(\"Completed oni.close\")\n                    // tslint:disable-next-line:no-empty\n                } catch (e) {}\n            }\n        })\n    })\n}\n"
  },
  {
    "path": "test/demo/DemoCommon.ts",
    "content": "/**\n * Script for hero screenshot on Oni's website and github\n */\n\nimport * as path from \"path\"\n\nimport * as mkdirp from \"mkdirp\"\n\nexport const getRootPath = () => {\n    return path.join(__dirname, \"..\", \"..\", \"..\")\n}\n\nexport const getDistPath = () => {\n    const distPath = path.join(getRootPath(), \"dist\", \"media\")\n    mkdirp.sync(distPath)\n    return distPath\n}\n"
  },
  {
    "path": "test/demo/HeroDemo.ts",
    "content": "/**\n * Script for demo on Oni's website\n */\n\nimport * as assert from \"assert\"\nimport { execSync } from \"child_process\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\nimport * as shell from \"shelljs\"\n\nimport * as rimraf from \"rimraf\"\n\nimport { getCompletionElement, getTemporaryFolder } from \"./../ci/Common\"\n\nimport { getDistPath, getRootPath } from \"./DemoCommon\"\n\nimport { remote } from \"electron\"\n\nconst BASEDELAY = 18\nconst RANDOMDELAY = 8\n\nconst EmptyConfigPath = path.join(getTemporaryFolder(), \"config.js\")\n\nconst getProjectRootPath = () => {\n    const root = getRoot(__dirname)\n    return os.platform() === \"win32\" ? root : os.homedir()\n}\n\nconst ReactProjectName = \"oni-react-app\"\n\nconst getRoot = (dir: string): string => {\n    const parent = path.dirname(dir)\n    if (parent === dir) {\n        return parent\n    } else {\n        return getRoot(parent)\n    }\n}\n\nconst createReactAppProject = oni => {\n    const oniReactApp = path.join(getProjectRootPath(), ReactProjectName)\n\n    // rimraf.sync(oniReactApp)\n    // const output = execSync('create-react-app \"' + oniReactApp + '\"')\n\n    const oniLogoPath = path.join(getRootPath(), \"images\", \"256x256.png\")\n    const oniLogoDestinationPath = path.join(oniReactApp, \"src\", \"oni.png\")\n\n    const oniLogoComponentPath = path.join(oniReactApp, \"src\", \"OniLogo.js\")\n\n    fs.writeFileSync(\n        oniLogoComponentPath,\n        `\nimport React, { Component } from 'react';\nimport logo from './oni.png';\n\nexport class OniLogo extends Component {\n  render() {\n    return <img src={logo} className=\"App-logo\" alt=\"logo\" />;\n  }\n}\n    `,\n        \"utf8\",\n    )\n\n    // Delete the 'App.test.js' so it doesn't mess up fuzzy find results\n    rimraf.sync(path.join(oniReactApp, \"src\", \"App.test.js\"))\n\n    shell.cp(oniLogoPath, oniLogoDestinationPath)\n    shell.cp(path.join(oniReactApp, \"src\", \"Old.js\"), path.join(oniReactApp, \"src\", \"App.js\"))\n    return oniReactApp\n}\n\nexport const test = async (oni: any) => {\n    const reactAppPath = createReactAppProject(oni)\n\n    await oni.automation.waitForEditors()\n\n    oni.workspace.changeDirectory(reactAppPath)\n\n    const isMac = process.platform === \"darwin\"\n\n    const shortDelay = async () => oni.automation.sleep(BASEDELAY * 25)\n    const longDelay = async () => oni.automation.sleep(BASEDELAY * 50)\n\n    const simulateTyping = async (keys: string, baseDelay: number = BASEDELAY) => {\n        for (const key of keys) {\n            oni.automation.sendKeysV2(key)\n            await oni.automation.sleep(baseDelay + Math.random() * RANDOMDELAY)\n        }\n        await shortDelay()\n    }\n\n    const pressEscape = async () => {\n        await shortDelay()\n        oni.automation.sendKeysV2(\"<esc>\")\n        await shortDelay()\n    }\n\n    const pressTab = async () => {\n        await shortDelay()\n        oni.automation.sendKeysV2(\"<tab>\")\n        await shortDelay()\n    }\n\n    const pressShiftTab = async () => {\n        await shortDelay()\n        oni.automation.sendKeysV2(\"<s-tab>\")\n        await shortDelay()\n    }\n\n    const pressEnter = async () => {\n        await shortDelay()\n        oni.automation.sendKeysV2(\"<cr>\")\n        await shortDelay()\n    }\n\n    const openCommandPalette = async () => {\n        await shortDelay()\n        const keys = isMac ? \"<m-s-p>\" : \"<c-s-p>\"\n        oni.automation.sendKeysV2(keys)\n        await shortDelay()\n    }\n\n    const openFindInFiles = async () => {\n        await shortDelay()\n        const keys = isMac ? \"<m-s-f>\" : \"<c-s-f>\"\n        oni.automation.sendKeysV2(keys)\n        await shortDelay()\n    }\n\n    const openQuickOpen = async () => {\n        await shortDelay()\n        const keys = isMac ? \"<m-p>\" : \"<c-p>\"\n        oni.automation.sendKeysV2(keys)\n        await shortDelay()\n    }\n\n    const splitHorizontal = async (fileName: string) => {\n        await shortDelay()\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-s>\")\n        await shortDelay()\n        await simulateTyping(\":tabnew VIM.md\")\n    }\n\n    const waitForCompletion = async () => {\n        return oni.automation.waitFor(() => !!getCompletionElement())\n    }\n\n    const showWelcomeAchievement = async () => {\n        oni.achievements.clearAchievements()\n\n        // Create our own 'mock' achievement, because\n        // the welcome one won't be tracked if it has been completed\n        oni.achievements.registerAchievement({\n            uniqueId: \"oni.achievement.automation\",\n            name: \"Welcome to Oni!\",\n            description: \"Launch Oni for the first time\",\n            goals: [\n                {\n                    name: null,\n                    goalId: \"oni.automation.goal\",\n                    count: 1,\n                },\n            ],\n        })\n        oni.achievements.notifyGoal(\"oni.automation.goal\")\n\n        await longDelay()\n        await longDelay()\n    }\n\n    const intro = async () => {\n        await simulateTyping(\":tabnew Hello.md\")\n        await pressEnter()\n\n        await simulateTyping(\n            \"iOni is a new kind of editor: combining the best of Vim, Atom, and VSCode.\",\n        )\n        await pressEnter()\n        await simulateTyping(\n            \"Built with web tech, featuring a high performance canvas renderer, with (neo)vim handling the heavy lifting.\",\n        )\n        await pressEnter()\n        await simulateTyping(\"Available for Windows, OSX, and Linux.\")\n\n        await pressEscape()\n    }\n\n    const navigateToSneakWithTag = async (tag: string) => {\n        oni.automation.sendKeysV2(\"<c-g>\")\n        await shortDelay()\n\n        const targetSneak = oni.sneak.getSneakMatchingTag(tag)\n        const triggerKeys = targetSneak.triggerKeys as string\n        await simulateTyping(triggerKeys)\n        await shortDelay()\n    }\n\n    const showKeyboardNavigation = async () => {\n        await splitHorizontal(\"VIM.md\")\n        await pressEnter()\n\n        await simulateTyping(\"i\")\n        await simulateTyping(\"Use your Vim muscle memory to be productive without a mouse...\")\n\n        await pressEscape()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-h>\")\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"G\")\n        await longDelay()\n        oni.automation.sendKeysV2(\"gg\")\n        await longDelay()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-h>\")\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-l>\")\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-l>\")\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-j>\")\n        await shortDelay()\n\n        await simulateTyping(\"o\")\n        await simulateTyping(\"..but enjoy the conveniences of a modern UI editor.\")\n        await pressEscape()\n\n        await shortDelay()\n\n        await navigateToSneakWithTag(\"oni.sidebar.search\")\n\n        await navigateToSneakWithTag(\"oni.sidebar.learning\")\n\n        await navigateToSneakWithTag(\"oni.sidebar.explorer\")\n\n        oni.automation.sendKeysV2(\"<esc>\")\n\n        await simulateTyping(\":qa!\")\n        oni.automation.sendKeysV2(\"<cr>\")\n\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"<esc>\")\n    }\n\n    const showDevelopment = async () => {\n        await pressEscape()\n\n        await openCommandPalette()\n        await simulateTyping(\"brovsp\")\n        await pressEnter()\n\n        await pressEscape()\n        await openCommandPalette()\n        await simulateTyping(\"termhzsp\")\n        await pressEnter()\n\n        await longDelay()\n\n        await simulateTyping(\"A\")\n        await simulateTyping(\"npm run start\")\n        await pressEnter()\n\n        await pressEscape()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-h>\")\n        await shortDelay()\n\n        await openQuickOpen()\n        await simulateTyping(\"Appjs\")\n        await pressEnter()\n\n        await navigateToSneakWithTag(\"browser.address\")\n\n        await shortDelay()\n\n        await simulateTyping(\"http://localhost:3000\")\n        await pressEnter()\n\n        // The popped up browser can steal focus, causing our bindings to fail..\n        require(\"electron\")\n            .remote.getCurrentWindow()\n            .focus()\n\n        await simulateTyping(\"10j\")\n        await shortDelay()\n        await simulateTyping(\"cit\")\n        await shortDelay()\n        await simulateTyping(\"Welcome to Oni\")\n        await pressEscape()\n        await simulateTyping(\":w\")\n        await pressEnter()\n        await shortDelay()\n\n        await simulateTyping(\"7k\")\n        await simulateTyping(\"O\")\n        await simulateTyping(\"impsnip\")\n\n        await waitForCompletion()\n\n        await pressEnter()\n\n        await shortDelay()\n        await simulateTyping(\"./Oni\")\n        await waitForCompletion()\n        await pressEnter()\n\n        await pressTab()\n        await simulateTyping(\"Oni\")\n        await waitForCompletion()\n        await pressEnter()\n        await pressTab()\n\n        await simulateTyping(\"7j\")\n        await simulateTyping(\"b\")\n        await simulateTyping(\"C\")\n        await simulateTyping(\"OniLogo />\")\n\n        await pressEscape()\n        await simulateTyping(\":w\")\n        await pressEnter()\n        await longDelay()\n        await longDelay()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-l>\")\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"<c-w>\")\n        oni.automation.sendKeysV2(\"<c-j>\")\n        await shortDelay()\n\n        await simulateTyping(\":q\")\n        await pressEnter()\n        await shortDelay()\n\n        await simulateTyping(\":q\")\n        await pressEnter()\n        await shortDelay()\n    }\n\n    const showConfig = async () => {\n        await pressEscape()\n        await openCommandPalette()\n\n        await simulateTyping(\"configuser\")\n        await longDelay()\n        await pressEnter()\n\n        await longDelay()\n\n        oni.automation.sendKeysV2(\"/\")\n        await shortDelay()\n        await simulateTyping(\"fontSize\")\n        await shortDelay()\n        oni.automation.sendKeysV2(\"<cr>\")\n\n        await shortDelay()\n        await simulateTyping(\"gcc\")\n        await shortDelay\n        await simulateTyping(\"fp\")\n        await longDelay()\n        await simulateTyping(\"ciw\")\n        await longDelay()\n        await simulateTyping(\"16px\")\n        await pressEscape()\n        await simulateTyping(\":w\")\n        await pressEscape()\n\n        // HACK - Configuration doesn't use the same file, so we need to set this directly here\n        oni.configuration.setValues({ \"editor.fontSize\": \"16px\" })\n\n        await longDelay()\n        await simulateTyping(\"b\")\n        await longDelay()\n        await simulateTyping(\"ciw\")\n        await longDelay()\n        await simulateTyping(\"14px\")\n        await pressEscape()\n        await simulateTyping(\":w\")\n        await pressEnter()\n        oni.configuration.setValues({ \"editor.fontSize\": \"14px\" })\n        await longDelay()\n        await pressEscape()\n\n        await simulateTyping(\"gg\")\n        oni.automation.sendKeysV2(\"/\")\n        await shortDelay()\n        await simulateTyping(\"activate\")\n        await pressEnter()\n        await simulateTyping(\"n\")\n\n        await simulateTyping(\"o\")\n        await pressEnter()\n        await simulateTyping(\"// We can also use Oni's extensibility API here!\")\n        await pressEnter()\n        await simulateTyping(\"Let's add a status bar item\")\n        await pressEscape()\n        await simulateTyping(\"o\")\n        oni.automation.sendKeysV2(\"<c-w>\")\n        await pressEnter()\n\n        await simulateTyping(\"const statusBarItem = oni.s\")\n        await shortDelay()\n        await simulateTyping(\"tatusBar.c\")\n        await shortDelay()\n        await simulateTyping(\"reateItem(1)\")\n        await pressEnter()\n        await simulateTyping(\"statusBarItem.s\")\n        await shortDelay()\n        await simulateTyping(\"etContents(\")\n        await shortDelay()\n        oni.automation.sendKeys(\"<lt>\")\n        await simulateTyping(\"div>Hello World\")\n        oni.automation.sendKeys(\"<lt>\")\n        await simulateTyping(\"/div>)\")\n        await pressEnter()\n        await simulateTyping(\"statusBarItem.\")\n        await shortDelay()\n        await simulateTyping(\"show()\")\n        await pressEnter()\n\n        await pressEscape()\n        await simulateTyping(\":w\")\n        await pressEnter()\n\n        // const item = oni.statusBar.createItem(1)\n        // item.setContents(\"Hello World\")\n        // item.show()\n\n        await longDelay()\n\n        await simulateTyping(\":q\")\n        await pressEnter()\n\n        await simulateTyping(\":q\")\n        await pressEnter()\n    }\n\n    const showComingSoon = async () => {\n        await shortDelay()\n        await simulateTyping(\":tabnew SOON.md\")\n        await shortDelay()\n        await pressEnter()\n        await shortDelay()\n        await simulateTyping(\"i\")\n\n        await simulateTyping(\"This is just the beginning! Lots more to come:\")\n        await pressEnter()\n        await simulateTyping(\"* Live Preview\")\n        await pressEnter()\n        await simulateTyping(\"* Plugin Management\")\n        await pressEnter()\n        await simulateTyping(\"* More tutorials \")\n        await pressEnter()\n        await simulateTyping(\"* Debuggers\")\n        await pressEnter()\n        await simulateTyping(\"* Version Control Integration\")\n        await longDelay()\n        await pressEnter()\n        await pressEnter()\n        await simulateTyping(\"Thanks for watching! Download Oni today.\")\n\n        await pressEscape()\n    }\n\n    const showLanguageServices = async () => {\n        await simulateTyping(\":tabnew test.js\")\n        oni.automation.sendKeysV2(\"<cr>\")\n\n        await simulateTyping(\"i\")\n        await simulateTyping(\"// Oni integrates with language servers, and includes several...\")\n        oni.automation.sendKeysV2(\"<cr>\")\n        await simulateTyping(\"...but you can hook up your own, too!\")\n        await shortDelay()\n\n        oni.automation.sendKeysV2(\"<cr>\")\n        oni.automation.sendKeysV2(\"<c-w>\")\n        await shortDelay()\n        await simulateTyping(\"const myArray = [1, 2, 3]\")\n\n        await pressEnter()\n        await pressEnter()\n        await pressEscape()\n\n        await simulateTyping(\"O\")\n        await simulateTyping(\"const newArray = my\")\n        await waitForCompletion()\n        await shortDelay()\n        await simulateTyping(\"Array.\")\n\n        await simulateTyping(\"m\")\n        await longDelay()\n        await simulateTyping(\"ap(\")\n        await longDelay()\n        await simulateTyping(\"(val) => val + 1\")\n\n        await pressEscape()\n        await simulateTyping(\"o\")\n        await pressEnter()\n        await simulateTyping(\"// Oni also has snippet support:\")\n        await pressEnter()\n        oni.automation.sendKeysV2(\"<c-w>\")\n        await pressEnter()\n\n        await simulateTyping(\"forsnip\")\n        await pressEnter()\n\n        await pressTab()\n        await pressShiftTab()\n\n        await simulateTyping(\"idx\")\n        await pressTab()\n        await simulateTyping(\"myArray\")\n        await pressTab()\n        await pressTab()\n        await pressEscape()\n    }\n\n    const showTutorials = async () => {\n        await oni.editors.activeEditor.neovim.command(\":tabnew TUTORIAL\")\n\n        await simulateTyping(\"i\")\n        await simulateTyping(\n            \"If you're new to modal editing, Oni comes with interactive tutorials to get you up to speed!\",\n        )\n        await pressEscape()\n\n        await navigateToSneakWithTag(\"oni.sidebar.learning\")\n\n        const firstTutorialId = oni.tutorials.getNextTutorialId()\n        await oni.tutorials.startTutorial(firstTutorialId)\n\n        await shortDelay()\n        await pressEscape()\n\n        await simulateTyping(\"i\")\n        await shortDelay()\n        await simulateTyping(\"hello\")\n        await shortDelay()\n        await pressEscape()\n        await shortDelay()\n        await simulateTyping(\"o\")\n        await shortDelay()\n        await simulateTyping(\"world\")\n        await shortDelay()\n        await pressEscape()\n\n        await longDelay()\n        await oni.editors.activeEditor.neovim.command(\":q!\")\n    }\n\n    // Prime the typescript language service prior to recording\n    await simulateTyping(\":tabnew\")\n    await pressEnter()\n    await openQuickOpen()\n    await simulateTyping(\"App.js\")\n    await pressEnter()\n\n    await simulateTyping(\"owindow.\")\n    await waitForCompletion()\n    await longDelay()\n    await pressEscape()\n    await simulateTyping(\":q!\")\n    await pressEnter()\n\n    oni.configuration.setValues({\n        \"ui.fontSize\": \"14px\",\n        \"editor.fontSize\": \"14px\",\n    })\n\n    // Set window size\n    remote.getCurrentWindow().setSize(1920, 1080)\n\n    oni.recorder.startRecording()\n\n    await showWelcomeAchievement()\n\n    oni.tutorials.clearProgress()\n\n    oni.commands.executeCommand(\"keyDisplayer.show\")\n    oni.configuration.setValues({\n        \"keyDisplayer.showInInsertMode\": false,\n        \"editor.split.mode\": \"oni\",\n        \"browser.defaultUrl\": \"https://github.com/onivim/oni\",\n    })\n\n    await intro()\n\n    await showKeyboardNavigation()\n\n    await showDevelopment()\n\n    // ---\n    await showLanguageServices()\n    // ---\n\n    // oni.automation.sendKeysV2(\"<c-w>\")\n    // oni.automation.sendKeysV2(\"<c-k>\")\n\n    // await simulateTyping(\"o\")\n    // await simulateTyping(\"...or the embedded file finder.\")\n    // await shortDelay()\n\n    // await pressEscape()\n    // await shortDelay()\n    // await openQuickOpen()\n    // await simulateTyping(\"NeovimEditor\")\n    // await shortDelay()\n    // oni.automation.sendKeysV2(\"<cr>\")\n    // await longDelay()\n    // oni.automation.sendKeysV2(\"<c-o>\")\n    // await shortDelay()\n\n    // await simulateTyping(\"G\")\n    // await simulateTyping(\"o\")\n    // await simulateTyping(\"...use the built in command palette to discover functionality.\")\n    // await pressEscape()\n    await showTutorials()\n\n    await showConfig()\n\n    await showComingSoon()\n\n    await simulateTyping(\":q\")\n    await longDelay()\n\n    oni.configuration.setValues({ \"recorder.outputPath\": getDistPath() })\n    oni.recorder.stopRecording(`demo-${process.platform}.webm`)\n\n    await pressEscape()\n}\n\nexport const settings = {\n    configPath: EmptyConfigPath,\n}\n"
  },
  {
    "path": "test/demo/HeroScreenshot.ts",
    "content": "/**\n * Script for hero screenshot on Oni's website and github\n */\n\nimport * as assert from \"assert\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport { remote } from \"electron\"\n\nimport { getCompletionElement } from \"../ci/Common\"\nimport { getDistPath, getRootPath } from \"./DemoCommon\"\n\n// tslint:disable:no-console\nconst getNotificationText = () => {\n    const elements = document.body.getElementsByClassName(\"notification-description\")\n\n    if (!elements || !elements.length) {\n        return null\n    } else {\n        return elements[0].innerHTML\n    }\n}\n\nexport const test = async (oni: any) => {\n    await oni.automation.waitForEditors()\n\n    // Use the `Completion.ts` file as the screenshot source\n    remote.getCurrentWindow().setSize(1200, 800)\n\n    const outputPath = getDistPath()\n\n    await oni.workspace.changeDirectory(getRootPath())\n\n    const filePath = path.join(\n        getRootPath(),\n        \"browser\",\n        \"src\",\n        \"Services\",\n        \"Language\",\n        \"LanguageStore.ts\",\n    )\n\n    oni.automation.sendKeys(\":e WELCOME.md<CR>\")\n\n    await oni.automation.sleep(500)\n\n    oni.automation.sendKeys(\":e \" + filePath + \"<CR>\")\n\n    await oni.automation.waitFor(() => oni.editors.activeEditor.activeBuffer.filePath === filePath)\n\n    oni.automation.sendKeys(\"/switchMap<CR>\")\n\n    await oni.automation.sleep(500)\n\n    oni.automation.sendKeys(\"<ESC>zz\")\n\n    await oni.automation.sleep(500)\n\n    oni.automation.sendKeys(\"O\")\n    oni.automation.sendKeys(\"<TAB><TAB>.audi\")\n\n    await oni.automation.sleep(500)\n\n    oni.automation.sendKeys(\"tTime((action\")\n\n    await oni.automation.sleep(500)\n\n    await oni.automation.waitFor(() => getCompletionElement() !== null, 20000)\n\n    await oni.automation.sleep(500)\n\n    oni.configuration.setValues({ \"recorder.outputPath\": outputPath })\n\n    oni.recorder.takeScreenshot(`screenshot-${process.platform}.png`)\n    await oni.automation.waitFor(() => getNotificationText() !== null, 20000)\n    console.log(\"Alert text (screenshot output path): \" + getNotificationText())\n}\n\nexport const settings = {\n    config: {\n        \"notifications.enabled\": true,\n    },\n}\n"
  },
  {
    "path": "test/setup/WindowsInstallerTests.ts",
    "content": "/**\n * WindowsInstallerTests\n */\n\nimport * as assert from \"assert\"\nimport * as cp from \"child_process\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nconst rootPath = path.join(__dirname, \"..\", \"..\", \"..\")\nconst packageJsonPath = path.join(rootPath, \"package.json\")\nconst oniVersion = require(packageJsonPath).version // tslint:disable-line\n\nlet arch = os.arch() === \"x32\" ? \"-ia32\" : \"\"\n\nif (process.env.APPVEYOR) {\n    arch = process.env.PLATFORM === \"x86\" ? \"-ia32\" : \"\"\n}\n\nconst installExecutablePath = path.join(rootPath, \"dist\", `Oni-${oniVersion}${arch}-win.exe`)\n\nconst runInstaller = (setupExecutablePath: string, installDirectory: string) => {\n    const doesInstallerExist = fs.existsSync(setupExecutablePath)\n\n    assert.strictEqual(\n        doesInstallerExist,\n        true,\n        \"Validate installer exists at: \" + setupExecutablePath,\n    )\n\n    return cp.spawnSync(installExecutablePath, [\n        \"/silent\",\n        \"/norestart\",\n        `/dir=${installDirectory}`,\n    ])\n}\n\nconst runUninstaller = (uninstallerExecutablePath: string) => {\n    return cp.spawnSync(uninstallerExecutablePath, [\"/silent\", \"/norestart\"])\n}\n\nconst getPathRegistryKey = () => {\n    // Use the `reg` command line tool to get information about the registry key\n    // Use `reg /?` or `reg query /?` at the command line ot get more info\n\n    const result = cp.spawnSync(\"reg\", [\"query\", \"HKCU\\\\Environment\", \"/e\", \"/f\", \"PATH\"])\n\n    const output = result.output.toString()\n\n    // the output is multi-line, so we'll split it up\n    const [, , lastLine] = output.split(\"\\r\\n\")\n\n    return lastLine.substring(29, lastLine.length)\n}\n\nconst log = msg => console.log(msg) // tslint:disable-line\n\nif (os.platform() === \"win32\") {\n    describe(\"WindowsInstallerTests\", () => {\n        it(\"installs / uninstalls to a test directory\", () => {\n            const testDirectory = \"oni-test-install-\" + new Date().getTime()\n            const testPath = path.join(\"C:\", testDirectory)\n\n            log(\"Installing to: \" + testPath)\n            const result = runInstaller(installExecutablePath, testPath)\n\n            const doesInstallFolderExist = fs.existsSync(testPath)\n            assert.strictEqual(doesInstallFolderExist, true, \"Validate install folder exists now\")\n\n            const doesOniExeExists = fs.existsSync(path.join(testPath, \"Oni.exe\"))\n            assert.strictEqual(doesOniExeExists, true, \"Validate Oni.exe exists\")\n\n            const uninstallExecutablePath = path.join(testPath, \"unins000.exe\")\n            const doesUninstallExist = fs.existsSync(uninstallExecutablePath)\n            assert.strictEqual(doesUninstallExist, true, \"Validate uninstaller exists\")\n\n            const pathKey = getPathRegistryKey()\n            assert.ok(\n                pathKey.indexOf(testDirectory) >= 0,\n                \"Validate path was added to registry key\",\n            )\n\n            log(\"Running uninstaller...\")\n            const uninstallResult = runUninstaller(uninstallExecutablePath)\n\n            assert.strictEqual(\n                doesInstallFolderExist,\n                true,\n                \"Validate install folder doesn't exist after uninstall\",\n            )\n\n            const pathKey2 = getPathRegistryKey()\n            assert.ok(\n                pathKey2.indexOf(testDirectory) === -1,\n                \"Validate path was removed from registry after installation\",\n            )\n        })\n    })\n}\n"
  },
  {
    "path": "test/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"target\": \"es2015\",\n        \"noImplicitAny\": false,\n        \"sourceMap\": false,\n        \"allowJs\": true,\n        \"outDir\": \"../lib_test\",\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"skipLibCheck\": true\n    },\n    \"include\": [\"**/*.tsx\", \"**/*.ts\", \"**/*.js\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "tslint.json",
    "content": "{\n    \"extends\": \"tslint:latest\",\n    \"cliOptions\": {\n        \"exclude\": [\"test/ci/*.js\"]\n    },\n    \"rules\": {\n        \"align\": false,\n        \"arrow-parens\": [false],\n        \"max-classes-per-file\": [false],\n        \"max-line-length\": [false],\n        \"no-implicit-dependencies\": false,\n        \"no-object-literal-type-assertion\": false,\n        \"no-submodule-imports\": false,\n        \"no-reference\": false,\n        \"no-namespace\": false,\n        \"object-literal-key-quotes\": false,\n        \"object-literal-sort-keys\": false,\n        \"semicolon\": false,\n        \"interface-name\": [false],\n        \"variable-name\": [\n            true,\n            \"allow-leading-underscore\",\n            \"allow-pascal-case\",\n            \"ban-keywords\",\n            \"check-format\"\n        ],\n        \"whitespace\": false,\n        \"no-trailing-whitespace\": [true, \"ignore-template-strings\"],\n        \"trailing-comma\": [\n            true,\n            {\n                \"multiline\": {\n                    \"objects\": \"always\",\n                    \"arrays\": \"always\",\n                    \"functions\": \"always\",\n                    \"typeLiterals\": \"ignore\"\n                },\n                \"esSpecCompliant\": true\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "ui-tests/BrowserView.test.tsx",
    "content": "import { WebviewTag } from \"electron\"\nimport { shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport { Event } from \"oni-types\"\nimport {\n    BrowserView,\n    IBrowserViewProps,\n    IBrowserViewState,\n} from \"../browser/src/Services/Browser/BrowserView\"\nimport { Configuration } from \"../browser/src/Services/Configuration\"\n\nconst mockEvent = new Event<void>()\nconst dispatch = () => mockEvent.dispatch()\n\nconst MockWebviewElement = (spy: (args?: any) => void) =>\n    ({\n        sendInputEvent(args) {\n            spy(args)\n        },\n    } as WebviewTag)\n\n// Using the disable life cycle methods here as the CDM calls sneak which is\n// an external dependency I'm not trying to test here\n\ndescribe(\"<BrowserView /> Tests\", () => {\n    const component = (\n        <BrowserView\n            initialUrl={\"test.com\"}\n            configuration={{} as Configuration}\n            debug={mockEvent}\n            goBack={mockEvent}\n            goForward={mockEvent}\n            reload={mockEvent}\n            scrollUp={mockEvent}\n            scrollLeft={mockEvent}\n            scrollRight={mockEvent}\n            scrollDown={mockEvent}\n        />\n    )\n    const wrapper = shallow<IBrowserViewProps, IBrowserViewState>(component, {\n        disableLifecycleMethods: true,\n    })\n    // can be typed here but the _webviewComponent is expected - TS Error\n    const instance: any = wrapper.instance()\n    it(\"component to render correctly\", () => {\n        expect(wrapper).toBeDefined()\n    })\n    it('Should correctly prefix a url with \"https\" or \"http\" if needed', () => {\n        expect(instance.prefixUrl(\"apple.com\")).toBe(\"http://apple.com\")\n    })\n    it('Should NOT prefix a url with \"https\" or \"http\" if already present', () => {\n        // subtle difference here as the function always add https as a prefix not http\n        expect(instance.prefixUrl(\"https://www.apple.com\")).toBe(\"https://www.apple.com\")\n    })\n\n    it(\"Should match the recent snapshot - unless an intentional change has occurred \", () => {\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n    it(\"it should call the sendInputEvent method of the mocked webview element on Scroll down\", () => {\n        const typedInstance: BrowserView = instance\n        const spy = jest.fn()\n        typedInstance._webviewElement = MockWebviewElement(spy)\n        typedInstance._scrollDown()\n        // the spy is passed to the mocked webview element so given that it was called the method accurately\n        // accessed the method on the webview\n        expect(spy).toHaveBeenCalled()\n        const args = {\n            type: \"keyDown\",\n            keyCode: \"Down\",\n            canScroll: true,\n            modifiers: [\"isAutoRepeat\"],\n        }\n        expect(spy.mock.calls[0][0]).toMatchObject(args)\n    })\n    it(\"it should call the sendInputEvent method of the mocked webview element on Scroll up\", () => {\n        const typedInstance: BrowserView = instance\n        const spy = jest.fn()\n        typedInstance._webviewElement = MockWebviewElement(spy)\n        typedInstance._scrollUp()\n        // the spy is passed to the mocked webview element so given that it was called the method accurately\n        // accessed the method on the webview\n        expect(spy).toHaveBeenCalled()\n        const args = {\n            type: \"keyDown\",\n            keyCode: \"Up\",\n            canScroll: true,\n            modifiers: [\"isAutoRepeat\"],\n        }\n        expect(spy.mock.calls[0][0]).toMatchObject(args)\n    })\n    it(\"it should call the sendInputEvent method of the mocked webview element on Scroll left\", () => {\n        const typedInstance: BrowserView = instance\n        const spy = jest.fn()\n        typedInstance._webviewElement = MockWebviewElement(spy)\n        typedInstance._scrollLeft()\n        expect(spy).toHaveBeenCalled()\n        const args = {\n            type: \"keyDown\",\n            keyCode: \"Left\",\n            canScroll: true,\n            modifiers: [\"isAutoRepeat\"],\n        }\n        expect(spy.mock.calls[0][0]).toMatchObject(args)\n    })\n    it(\"it should call the sendInputEvent method of the mocked webview element on Scroll right\", () => {\n        const typedInstance: BrowserView = instance\n        const spy = jest.fn()\n        typedInstance._webviewElement = MockWebviewElement(spy)\n        typedInstance._scrollRight()\n        expect(spy).toHaveBeenCalled()\n        const args = {\n            type: \"keyDown\",\n            keyCode: \"Right\",\n            canScroll: true,\n            modifiers: [\"isAutoRepeat\"],\n        }\n        expect(spy.mock.calls[0][0]).toMatchObject(args)\n    })\n    it(\"it should NOT call the sendInputEvent method if no webview is present\", () => {\n        const typedInstance: BrowserView = instance\n        const spy = jest.fn()\n        typedInstance._webviewElement = null\n        typedInstance._scrollDown()\n        expect(spy.mock.calls.length).toBe(0)\n    })\n})\n"
  },
  {
    "path": "ui-tests/BufferManager.test.ts",
    "content": "import { BufferManager, InactiveBuffer } from \"./../browser/src/Editor/BufferManager\"\n\ndescribe(\"Buffer Manager Tests\", () => {\n    const neovim = {} as any\n    const actions = {} as any\n    const store = {\n        getState: jest.fn(),\n    } as any\n\n    const manager = new BufferManager(neovim, actions, store)\n\n    const event = {\n        bufferFullPath: \"/test/file\",\n        bufferTotalLines: 2,\n        bufferNumber: 1,\n        modified: false,\n        hidden: false,\n        listed: true,\n        version: 1,\n        line: 0,\n        column: 0,\n        byte: 8,\n        filetype: \"js\",\n        tabNumber: 1,\n        windowNumber: 1,\n        wincol: 10,\n        winline: 25,\n        windowTopLine: 0,\n        windowBottomLine: 200,\n        windowWidth: 100,\n        windowHeight: 100,\n        tabstop: 8,\n        shiftwidth: 2,\n        comments: \"://,ex:*/\",\n    }\n\n    const inactive1 = {\n        bufferNumber: 2,\n        bufferFullPath: \"/test/two\",\n        filetype: \"js\",\n        buftype: \"\",\n        modified: false,\n        hidden: false,\n        listed: true,\n        version: 1,\n    }\n\n    beforeEach(() => {\n        manager.updateBufferFromEvent(event)\n    })\n\n    it(\"Should correctly set buffer variables\", () => {\n        const buffer = manager.getBufferById(\"1\")\n        expect(buffer.tabstop).toBe(8)\n        expect(buffer.shiftwidth).toBe(2)\n        expect(buffer.comment.defaults.includes(\"//\")).toBe(true)\n        expect(buffer.comment.end.includes(\"*/\")).toBe(true)\n    })\n\n    it(\"Should correctly populate the buffer list\", () => {\n        manager.populateBufferList({\n            current: event,\n            existingBuffers: [inactive1],\n        })\n\n        const buffers = manager.getBuffers()\n        expect(buffers.length).toBe(2)\n        expect(buffers.find(buffer => buffer instanceof InactiveBuffer)).toBeTruthy()\n    })\n\n    it(\"Should correctly format a comment string (based on neovim &comment option)\", () => {\n        const buffer = manager.getBufferById(\"1\")\n        const comment = \"s1:/*,ex:*/,://,b:#,:%\"\n        const formatted = buffer.formatCommentOption(comment)\n        expect(formatted.start.includes(\"/*\")).toBeTruthy()\n        expect(formatted.end.includes(\"*/\")).toBeTruthy()\n        expect(formatted.defaults.includes(\"//\")).toBeTruthy()\n        expect(formatted.defaults.includes(\"#\")).toBeTruthy()\n    })\n\n    it(\"should correctly pass input to a layer that implements a handler\", () => {\n        store.getState.mockReturnValue({\n            layers: {\n                \"1\": [\n                    {\n                        handleInput: (key: string) => true,\n                        isActive: () => true,\n                    },\n                ],\n            },\n        })\n\n        const buffer = manager.getBufferById(\"1\")\n        const canHandleInput = buffer.handleInput(\"h\")\n        expect(canHandleInput).toBeTruthy()\n    })\n\n    it(\"should not allow handling of input if isActive does not exist on the layer\", () => {\n        store.getState.mockReturnValue({\n            layers: {\n                \"1\": [\n                    {\n                        handleInput: (key: string) => true,\n                    },\n                ],\n            },\n        })\n\n        const buffer = manager.getBufferById(\"1\")\n        const canHandleInput = buffer.handleInput(\"h\")\n        expect(canHandleInput).toBeFalsy()\n    })\n\n    it(\"should not intercept input for a layer that implements a handler but returns isActive = false\", () => {\n        store.getState.mockReturnValue({\n            layers: {\n                \"1\": [\n                    {\n                        handleInput: (key: string) => true,\n                        isActive: () => false,\n                    },\n                ],\n            },\n        })\n        const buffer = manager.getBufferById(\"1\")\n        const canHandleInput = buffer.handleInput(\"h\")\n        expect(canHandleInput).toBeFalsy()\n    })\n})\n"
  },
  {
    "path": "ui-tests/BufferScrollBar.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport toJson from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport { BufferScrollBar } from \"./../browser/src/UI/components/BufferScrollBar\"\n\ndescribe(\"<BufferScrollBar />\", () => {\n    const markers = [\n        {\n            line: 4,\n            height: 1,\n            color: \"yellow\",\n        },\n        {\n            line: 10,\n            height: 1,\n            color: \"red\",\n        },\n    ]\n    it(\"should render without crashing\", () => {\n        const wrapper = shallow(\n            <BufferScrollBar\n                visible\n                windowId={1}\n                bufferSize={30}\n                height={30}\n                windowTopLine={1}\n                windowBottomLine={25}\n                markers={markers}\n            />,\n        )\n        expect(wrapper.length).toBe(1)\n    })\n\n    it(\"should render the correct number of marker elements\", () => {\n        const wrapper = shallow(\n            <BufferScrollBar\n                visible\n                windowId={1}\n                bufferSize={30}\n                height={30}\n                windowTopLine={1}\n                windowBottomLine={25}\n                markers={markers}\n            />,\n        )\n        expect(wrapper.dive().find(\"#scrollbar-marker-element\").length).toBe(2)\n    })\n\n    it(\"should render only one marker if two marker elements share line\", () => {\n        const dupMarkers = [\n            ...markers,\n            {\n                line: 10,\n                height: 1,\n                color: \"yellow\",\n            },\n        ]\n        const wrapper = shallow(\n            <BufferScrollBar\n                visible\n                windowId={1}\n                bufferSize={30}\n                height={30}\n                windowTopLine={1}\n                windowBottomLine={25}\n                markers={dupMarkers}\n            />,\n        )\n        expect(wrapper.dive().find(\"#scrollbar-marker-element\").length).toBe(2)\n    })\n\n    it(\"should match last recorded snapshot\", () => {\n        const wrapper = shallow(\n            <BufferScrollBar\n                visible\n                windowId={1}\n                bufferSize={30}\n                height={30}\n                windowTopLine={1}\n                windowBottomLine={25}\n                markers={markers}\n            />,\n        )\n\n        expect(toJson(wrapper)).toMatchSnapshot()\n    })\n})\n"
  },
  {
    "path": "ui-tests/CommandLine.test.tsx",
    "content": "import { mount, shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\nimport { Provider } from \"react-redux\"\nimport configureStore, { MockStore, MockStoreCreator } from \"redux-mock-store\"\nimport ConnectCommand, { CommandLine } from \"../browser/src/UI/components/CommandLine\"\n\nconst mockStore: MockStoreCreator<IState> = configureStore()\n\ninterface IState {\n    commandLine: {\n        showIcons: boolean\n        visible: boolean\n        content: string\n        firstchar: string\n        position: number\n        level: number\n        prompt: string\n    }\n    configuration: {\n        \"experimental.commandline.icons\": boolean\n    }\n}\n\nconst initialState = {\n    commandLine: {\n        showIcons: true,\n        visible: true,\n        content: \"commandline test\",\n        firstchar: \":\",\n        position: 0,\n        level: 0,\n        prompt: \"\",\n    },\n    configuration: {\n        \"experimental.commandline.icons\": true,\n    },\n}\n\njest.mock(\"react-dom\")\n\ndescribe(\"<Commandline />\", () => {\n    let store: MockStore<IState>\n    let container: any\n\n    const CommandLineComponent = <CommandLine {...initialState.commandLine} />\n\n    beforeEach(() => {\n        store = mockStore(initialState)\n        container = mount(\n            <Provider store={store}>\n                <ConnectCommand />\n            </Provider>,\n        )\n    })\n\n    it(\"renders a shallow instance of the unconnected component\", () => {\n        const wrapper = shallow(CommandLineComponent)\n        expect(wrapper.length).toEqual(1)\n    })\n\n    it(\"should match last known snapshot unless we make a change\", () => {\n        const wrapper = shallow(CommandLineComponent)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n\n    it(\"should initially not have a focused state when rendered\", () => {\n        const wrapper = shallow(CommandLineComponent)\n        expect(wrapper.state().focused).toBe(false)\n    })\n\n    // REDUX CONNECTED COMPONENT TEST - full mount\n\n    it(\"renders the connected(Smart) component to ensure this components mounts\", () => {\n        expect(container.find(ConnectCommand).length).toEqual(1)\n    })\n})\n"
  },
  {
    "path": "ui-tests/ContextMenuComponent.test.tsx",
    "content": "import { mount, ReactWrapper } from \"enzyme\"\nimport toJson from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport {\n    ContextMenuItem,\n    ContextMenuView,\n    Detail,\n    IContextMenuItem,\n    IContextMenuItemProps,\n    Label,\n} from \"./../browser/src/Services/ContextMenu/ContextMenuComponent\"\n\ndescribe(\"<ContextMenuView />\", () => {\n    it(\"shows less than 10 items\", () => {\n        const itemsToRender: IContextMenuItem[] = createItems(8)\n\n        const wrapper = mount(\n            <ContextMenuView visible={true} base={\"\"} entries={itemsToRender} selectedIndex={5} />,\n        )\n\n        // expect(wrapper.html()).toEqual(\"\")\n        const renderedItems = wrapper.find(ContextMenuItem)\n        expect(renderedItems).toHaveLength(8)\n\n        expectRenderedItem(renderedItems.at(0), false, \"label_0\", \"detail of item 0\")\n        expectRenderedItem(renderedItems.at(1), false, \"label_1\", \"detail of item 1\")\n        expectRenderedItem(renderedItems.at(2), false, \"label_2\", \"detail of item 2\")\n        expectRenderedItem(renderedItems.at(3), false, \"label_3\", \"detail of item 3\")\n        expectRenderedItem(renderedItems.at(4), false, \"label_4\", \"detail of item 4\")\n        expectRenderedItem(renderedItems.at(5), true, \"label_5\", \"detail of item 5\")\n        expectRenderedItem(renderedItems.at(6), false, \"label_6\", \"detail of item 6\")\n        expectRenderedItem(renderedItems.at(7), false, \"label_7\", \"detail of item 7\")\n    })\n\n    it(\"scrolls when displaying more than 10 items\", () => {\n        const itemsToRender: IContextMenuItem[] = createItems(18)\n\n        const wrapper = mount(\n            <ContextMenuView visible={true} base={\"\"} entries={itemsToRender} selectedIndex={14} />,\n        )\n\n        const renderedItems = wrapper.find(ContextMenuItem)\n        expect(renderedItems).toHaveLength(10)\n\n        expectRenderedItem(renderedItems.at(0), false, \"label_5\", \"detail of item 5\")\n        expectRenderedItem(renderedItems.at(1), false, \"label_6\", \"detail of item 6\")\n        expectRenderedItem(renderedItems.at(2), false, \"label_7\", \"detail of item 7\")\n        expectRenderedItem(renderedItems.at(3), false, \"label_8\", \"detail of item 8\")\n        expectRenderedItem(renderedItems.at(4), false, \"label_9\", \"detail of item 9\")\n        expectRenderedItem(renderedItems.at(5), false, \"label_10\", \"detail of item 10\")\n        expectRenderedItem(renderedItems.at(6), false, \"label_11\", \"detail of item 11\")\n        expectRenderedItem(renderedItems.at(7), false, \"label_12\", \"detail of item 12\")\n        expectRenderedItem(renderedItems.at(8), false, \"label_13\", \"detail of item 13\")\n        expectRenderedItem(renderedItems.at(9), true, \"label_14\", \"detail of item 14\")\n    })\n})\n\nfunction createItems(count: number): IContextMenuItem[] {\n    const items: IContextMenuItem[] = []\n\n    for (let i = 0; i < count; i++) {\n        items.push({\n            label: \"label_\" + i,\n            detail: \"detail of item \" + i,\n        })\n    }\n\n    return items\n}\n\nfunction expectRenderedItem(\n    item: ReactWrapper<IContextMenuItemProps, any>,\n    selected: boolean,\n    label: string,\n    detail: string,\n) {\n    expect(item.prop(\"isSelected\")).toBe(selected)\n    expect(\n        item\n            .find(Label)\n            .first()\n            .text(),\n    ).toEqual(label)\n    expect(\n        item\n            .find(Detail)\n            .first()\n            .text(),\n    ).toEqual(detail)\n}\n"
  },
  {
    "path": "ui-tests/ErrorInfo.test.tsx",
    "content": "import * as React from \"react\"\nimport { shallow } from \"enzyme\"\nimport { Diagnostic } from \"vscode-languageserver-types\"\n\nimport { ErrorInfo, DiagnosticMessage } from \"../browser/src/UI/components/ErrorInfo\"\n\ndescribe(\"<ErrorInfo />\", () => {\n    const errors: Diagnostic[] = [\n        {\n            range: {\n                start: {\n                    line: 0,\n                    character: 0,\n                },\n                end: {\n                    line: 0,\n                    character: 10,\n                },\n            },\n            severity: 2,\n            code: 5,\n            source: \"test\",\n            message: \"an error here\",\n        },\n    ]\n\n    it(\"Should Render without crashing\", () => {\n        const wrapper = shallow(<ErrorInfo hasQuickInfo={true} errors={errors} />)\n        expect(wrapper.length).toBe(1)\n    })\n    it(\"Should Not Render without Errors\", () => {\n        const wrapper = shallow(<ErrorInfo hasQuickInfo={false} errors={null} />)\n        expect(wrapper.children().length).toBe(0)\n    })\n    it(\"Should render the correct diagnostic message\", () => {\n        const wrapper = shallow(<ErrorInfo hasQuickInfo={true} errors={errors} />)\n        expect(wrapper.dive().find(\"[data-id='diagnostic-message']\").length).toEqual(1)\n        expect(\n            wrapper\n                .dive()\n                .find(\"[data-id='diagnostic-message']\")\n                .dive()\n                .text(),\n        ).toBe(errors[0].message)\n    })\n\n    it(\"Should render the correct number of diagnostics\", () => {\n        const wrapper = shallow(\n            <ErrorInfo hasQuickInfo={true} errors={[...errors, ...errors, ...errors]} />,\n        )\n        expect(wrapper.dive().find(\"[data-id='diagnostic-message']\").length).toBe(3)\n    })\n\n    it(\"Should match the last snapshot on record unless a purposeful change was made\", () => {\n        const wrapper = shallow(\n            <ErrorInfo hasQuickInfo={true} errors={[...errors, ...errors, ...errors]} />,\n        )\n        expect(wrapper).toMatchSnapshot()\n    })\n})\n"
  },
  {
    "path": "ui-tests/ExplorerSplit.test.tsx",
    "content": "jest.mock(\"../browser/src/Services/WindowManager\")\njest.mock(\"../browser/src/Services/WindowManager/WindowManager\")\njest.mock(\"../browser/src/Services/Explorer/ExplorerView\")\njest.mock(\"../browser/src/Services/Explorer/ExplorerStore\")\n\nimport * as React from \"react\"\nimport { shallow } from \"enzyme\"\n\nimport MockOni from \"./mocks/Oni\"\n\nimport { createStore } from \"../browser/src/Services/Explorer/ExplorerStore\"\nimport { ExplorerSplit } from \"../browser/src/Services/Explorer/ExplorerSplit\"\n\ndescribe(\"ExplorerSplit\", () => {\n    let explorerSplit: ExplorerSplit\n    let store: Store<any>\n\n    beforeEach(() => {\n        store = {\n            dispatch: jest.fn(),\n            getState: jest.fn(),\n            subscribe: jest.fn(),\n            replaceReducer: jest.fn(),\n        } as Store<any>\n        ;(createStore as jest.Mock).mockReturnValue(store)\n\n        explorerSplit = new ExplorerSplit(new MockOni())\n    })\n\n    describe(\"locateFile\", () => {\n        it(\"dispatches SELECT_FILE when called\", () => {\n            explorerSplit.locateFile(\"/path/to/file.cpp\")\n\n            expect(store.dispatch).toHaveBeenCalledTimes(1)\n            expect(store.dispatch).toHaveBeenCalledWith({\n                type: \"SELECT_FILE\",\n                filePath: \"/path/to/file.cpp\",\n            })\n        })\n    })\n\n    describe(\"_onSelectionChanged\", () => {\n        let _getSelectedItem: jest.Mock\n\n        beforeEach(() => {\n            _getSelectedItem = explorerSplit[\"_getSelectedItem\"] = jest.fn()\n        })\n\n        it(\"dispatches SELECT_FILE_SUCCESS if fileToSelect matches selected item\", () => {\n            store.getState.mockReturnValue({ fileToSelect: \"/path/to/file.cpp\" })\n            _getSelectedItem.mockReturnValue({\n                type: \"file\",\n                filePath: \"/path/to/file.cpp\",\n            })\n\n            explorerSplit[\"_onSelectionChanged\"](\"a\")\n\n            expect(store.dispatch).not.toHaveBeenCalled()\n        })\n\n        it(\"does not dispatch SELECT_FILE_SUCCESS if fileToSelect isn't selected\", () => {\n            store.getState.mockReturnValue({ fileToSelect: \"/path/to/file.cpp\" })\n            _getSelectedItem.mockReturnValue({\n                type: \"file\",\n                filePath: \"/something/else.cpp\",\n            })\n\n            explorerSplit[\"_onSelectionChanged\"](\"a\")\n\n            expect(store.dispatch).not.toHaveBeenCalled()\n        })\n\n        it(\"does not dispatch SELECT_FILE_SUCCESS if there is no fileToSelect\", () => {\n            store.getState.mockReturnValue({ fileToSelect: null })\n\n            explorerSplit[\"_onSelectionChanged\"](\"a\")\n\n            expect(store.dispatch).not.toHaveBeenCalled()\n        })\n    })\n})\n"
  },
  {
    "path": "ui-tests/ExplorerView.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport * as React from \"react\"\nimport { createStore } from \"redux\"\n\nimport { Explorer } from \"../browser/src/Services/Explorer/ExplorerView\"\njest.mock(\"../browser/src/Services/Explorer/ExplorerSelectors\")\nimport * as ExplorerSelectors from \"../browser/src/Services/Explorer/ExplorerSelectors\"\nimport * as ExplorerState from \"../browser/src/Services/Explorer/ExplorerStore\"\n\ndescribe(\"<ExplorerView />\", () => {\n    let wrapper: any\n    let store: any\n\n    beforeEach(() => {\n        // Store that simply merges any action with the state.\n        store = createStore(\n            (state, action: any) => {\n                return { ...state, ...action.state }\n            },\n            { ...ExplorerState.DefaultExplorerState },\n        )\n        wrapper = shallow(\n            <Explorer\n                moveFileOrFolder={jest.fn()}\n                onSelectionChanged={jest.fn()}\n                onClick={jest.fn()}\n                onCancelRename={jest.fn()}\n                onCompleteRename={jest.fn()}\n            />,\n            { context: { store } },\n        )\n    })\n\n    it(\"sets idToSelect prop from fileToSelect state\", () => {\n        const mockMapStateToNodeList = ExplorerSelectors.mapStateToNodeList as jest.Mock\n        mockMapStateToNodeList.mockImplementation(\n            () =>\n                [\n                    {\n                        id: \"a\",\n                        type: \"file\",\n                        filePath: \"/root/workspace/dir1/dir2/file1.cpp\",\n                        modified: false,\n                        name: \"a name\",\n                        indentationLevel: 3,\n                    },\n                    {\n                        id: \"b\",\n                        type: \"file\",\n                        filePath: \"/root/workspace/dir1/dir3/file2.cpp\",\n                        modified: false,\n                        name: \"a name\",\n                        indentationLevel: 3,\n                    },\n                ] as ExplorerSelectors.ExplorerNode[],\n        )\n\n        expect(wrapper.props().idToSelect).toBeNull()\n        store.dispatch({\n            type: \"\",\n            state: { fileToSelect: \"/root/workspace/dir1/dir3/file2.cpp\" },\n        })\n        wrapper.update()\n        expect(wrapper.props().idToSelect).toEqual(\"b\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/ExternalMenus.test.tsx",
    "content": "import { mount, shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport { ExternalMenus } from \"./../browser/src/UI/components/ExternalMenus\"\n\ndescribe(\"<ExternalMenus />\", () => {\n    const wildMenu = {\n        selected: 0,\n        visible: false,\n        options: [\"test\"],\n    }\n\n    const commandLine = {\n        visible: true,\n        content: \"test\",\n        firstchar: \"t\",\n        position: 0,\n        prompt: \":\",\n        indent: 0,\n        level: 0,\n    }\n\n    it(\"Should render without crashing\", () => {\n        const wrapper = shallow(<ExternalMenus commandLine={commandLine} wildmenu={wildMenu} />)\n        expect(wrapper.length).toBe(1)\n    })\n    it(\"Should be present in the DOM even though hidden is true\", () => {\n        const hiddenCommandLine = { ...commandLine, visible: false }\n        const wrapper = shallow(\n            <ExternalMenus commandLine={hiddenCommandLine} wildmenu={wildMenu} />,\n        )\n        expect(wrapper.length).toBe(1)\n    })\n    it(\"Should match the last snapshot\", () => {\n        const wrapper = shallow(<ExternalMenus commandLine={commandLine} wildmenu={wildMenu} />)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n})\n"
  },
  {
    "path": "ui-tests/HighlightText.test.tsx",
    "content": "import { mount, shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport * as os from \"os\"\n\nimport { HighlightTextByIndex } from \"./../browser/src/UI/components/HighlightText\"\n\nconst highlightComponent = \"em\"\n\nconst initialState = {\n    highlightComponent,\n    highlightIndices: [0, 1, 3, 4],\n    text: \"highlight text\",\n    className: \"test-class\",\n}\n\ndescribe(\"<HighlightTextByIndex />\", () => {\n    it(\"renders a shallow instance of the component\", () => {\n        const component = shallow(<HighlightTextByIndex {...initialState} />)\n\n        expect(component.length).toEqual(1)\n    })\n\n    it(\"renders the correct text with highlights\", () => {\n        const component = mount(<HighlightTextByIndex {...initialState} />)\n\n        // Check the correct text is there\n        expect(component.text()).toContain(\"highlight text\")\n\n        // Check the structure is correct\n        expect(component.text()).toHaveLength(14)\n\n        // Check only 4 chars were highlighed\n        expect(component.find(\"em\")).toHaveLength(4)\n    })\n\n    it(\"renders the correct text with no highlights\", () => {\n        const testState = {\n            highlightComponent,\n            highlightIndices: [],\n            text: \"no highlight text\",\n            className: \"test-class\",\n        }\n\n        const component = mount(<HighlightTextByIndex {...testState} />)\n\n        // Check the correct text is there\n        expect(component.text()).toContain(\"no highlight text\")\n\n        // Check the structure is correct\n        expect(component.text()).toHaveLength(17)\n\n        // Check no chars were highlighed\n        expect(component.find(\"em\")).toHaveLength(0)\n    })\n\n    it(\"doesn't crash when passed a non-string\", () => {\n        const testState = {\n            highlightComponent,\n            highlightIndices: [0, 1, 3, 4],\n            text: 10101,\n            className: \"test-class\",\n        } as any\n\n        const component = mount(<HighlightTextByIndex {...testState} />)\n\n        // Should be length one, as only the out span is returned\n        // due to no inner text.\n        expect(component.find(\"span\")).toHaveLength(1)\n        expect(component.text() === \"\")\n        expect(component.hasClass(\"highlight-test\") === false)\n    })\n})\n"
  },
  {
    "path": "ui-tests/NeovimBufferLayersView.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport { BufferLayer, BufferLayerRenderContext } from \"oni-api\"\nimport * as React from \"react\"\n\nimport { IBufferLayer } from \"./../browser/src/Editor/NeovimEditor/BufferLayerManager\"\nimport { NeovimBufferLayersView } from \"./../browser/src/Editor/NeovimEditor/NeovimBufferLayersView\"\nimport { IWindow } from \"./../browser/src/Editor/NeovimEditor/NeovimEditorStore\"\n\ndescribe(\"<NeovimBufferLayersView/>\", () => {\n    const mockLayer: IBufferLayer = {\n        id: \"test layer\",\n        render: jest.fn().mockReturnValue(<div id=\"test-layer\">layer</div>),\n    }\n    const layers = { 2: [mockLayer] }\n    const windows: IWindow[] = [\n        {\n            file: \"test.txt\",\n            bufferId: 2,\n            windowId: 1,\n            column: 4,\n            line: 2,\n\n            bufferToScreen: jest.fn(),\n            screenToPixel: jest.fn().mockReturnValue({\n                screenX: 20,\n                screenY: 30,\n            }),\n            bufferToPixel: jest.fn(),\n\n            dimensions: { x: 0, y: 0, width: 100, height: 40 },\n            topBufferLine: 20,\n            bottomBufferLine: 40,\n\n            visibleLines: [\"test string\", \"test string\", \"test string\"],\n        },\n    ]\n    it(\"Should render without crashing\", () => {\n        const wrapper = shallow(\n            <NeovimBufferLayersView\n                fontPixelHeight={10}\n                fontPixelWidth={3}\n                layers={layers}\n                activeWindowId={1}\n                windows={windows}\n            />,\n        )\n\n        expect(wrapper.length).toBe(1)\n    })\n\n    it(\"should render the layers contents\", () => {\n        const wrapper = shallow(\n            <NeovimBufferLayersView\n                fontPixelHeight={10}\n                fontPixelWidth={3}\n                layers={layers}\n                activeWindowId={1}\n                windows={windows}\n            />,\n        )\n\n        expect(wrapper.find(\"#test-layer\").length).toBe(1)\n    })\n    it(\"should call the layers render function with the correct args\", () => {\n        const wrapper = shallow(\n            <NeovimBufferLayersView\n                fontPixelHeight={10}\n                fontPixelWidth={3}\n                layers={layers}\n                activeWindowId={1}\n                windows={windows}\n            />,\n        )\n\n        const context = (mockLayer.render as any).mock.calls[0][0]\n        expect(context).toEqual({\n            isActive: true,\n            windowId: 1,\n            fontPixelWidth: 3,\n            fontPixelHeight: 10,\n            cursorColumn: 4,\n            cursorLine: 2,\n            bufferToScreen: windows[0].bufferToScreen,\n            screenToPixel: windows[0].screenToPixel,\n            bufferToPixel: windows[0].bufferToPixel,\n            dimensions: windows[0].dimensions,\n            visibleLines: [\"test string\", \"test string\", \"test string\"],\n            topBufferLine: 20,\n            bottomBufferLine: 40,\n        })\n    })\n})\n"
  },
  {
    "path": "ui-tests/NodeView.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport { DragAndDrop } from \"./../browser/src/Services/DragAndDrop\"\nimport { ExplorerNode } from \"./../browser/src/Services/Explorer/ExplorerSelectors\"\nimport { NodeView, NodeWrapper } from \"./../browser/src/Services/Explorer/ExplorerView\"\nimport { TextInputView } from \"./../browser/src/UI/components/LightweightText\"\n\ndescribe(\"<NodeView />\", () => {\n    const testNode = {\n        id: \"2\",\n        filePath: \"/test/a/file.txt\",\n        type: \"file\",\n        modified: false,\n        name: \"file.txt\",\n        indentationLevel: 2,\n    } as ExplorerNode\n\n    const Node = (\n        <NodeView\n            yanked={[] as string[]}\n            measure={() => null}\n            isCreating={false}\n            isRenaming={testNode}\n            moveFileOrFolder={() => ({})}\n            node={testNode}\n            isSelected={false}\n            onClick={() => ({})}\n            onCancelRename={() => ({})}\n            onCompleteRename={() => ({})}\n        />\n    )\n    it(\"Should render without crashing\", () => {\n        const wrapper = shallow(Node)\n        expect(wrapper.length).toEqual(1)\n    })\n\n    it(\"Should render and input element if the selected element is renaming\", () => {\n        const wrapper = shallow(\n            <NodeView\n                yanked={[] as string[]}\n                measure={() => null}\n                isCreating={false}\n                isRenaming={testNode}\n                moveFileOrFolder={() => ({})}\n                node={testNode}\n                isSelected={true}\n                onClick={() => ({})}\n                onCancelRename={() => ({})}\n                onCompleteRename={() => ({})}\n            />,\n        )\n\n        const input = wrapper.find(TextInputView)\n        expect(input.length).toEqual(1)\n    })\n\n    it(\"Should render the node if the selected element is not renaming\", () => {\n        const wrapper = shallow(Node)\n        expect(\n            wrapper\n                .find(NodeWrapper)\n                .dive()\n                .find(DragAndDrop),\n        ).toHaveLength(1)\n    })\n\n    it(\"Should match the snapshot\", () => {\n        const wrapper = shallow(Node)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n})\n"
  },
  {
    "path": "ui-tests/NotificationView.test.tsx",
    "content": "import { mount, shallow, configure } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport styled from \"styled-components\"\nimport {\n    Button,\n    NotificationContents,\n    NotificationDescription,\n    NotificationTitle,\n    NotificationView,\n} from \"./../browser/src/Services/Notifications/NotificationsView\"\n\ndescribe(\"<NotificationsView />\", () => {\n    const buttons = [\n        {\n            title: \"yes\",\n            callback: () => ({}),\n        },\n        {\n            title: \"no\",\n            callback: () => ({}),\n        },\n    ]\n    const Notification = (\n        <NotificationView\n            id=\"1\"\n            level=\"info\"\n            title=\"testing1\"\n            detail=\"this is a test\"\n            expirationTime={20000000}\n            onClick={() => console.log(\"clicked\")} //tslint:disable-line\n            onClose={() => console.log(\"closed\")} //tslint:disable-line\n        />\n    )\n\n    const NotificationWithButtons = (\n        <NotificationView\n            id=\"1\"\n            level=\"info\"\n            title=\"testing1\"\n            detail=\"this is a test\"\n            expirationTime={20000000}\n            onClick={() => console.log(\"clicked\")} //tslint:disable-line\n            onClose={() => console.log(\"closed\")} //tslint:disable-line\n            buttons={buttons}\n        />\n    )\n    it(\"It renders a notification component correctly\", () => {\n        const wrapper = shallow(Notification)\n        expect(wrapper.length).toEqual(1)\n    })\n\n    it(\"Renders the correct title\", () => {\n        const wrapper = shallow(Notification)\n        expect(\n            wrapper\n                .find(NotificationTitle)\n                .dive()\n                .text(),\n        ).toEqual(\"testing1\")\n    })\n\n    it(\"Renders the correct text\", () => {\n        const wrapper = shallow(Notification)\n        expect(\n            wrapper\n                .find(NotificationContents)\n                .dive()\n                .find(NotificationDescription)\n                .dive()\n                .text(),\n        ).toEqual(\"this is a test\")\n    })\n\n    it(\"should match the snapshot\", () => {\n        const wrapper = shallow(Notification)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n\n    it(\"Renders buttons with correct text when passed button fields\", () => {\n        const wrapper = shallow(NotificationWithButtons)\n        expect(wrapper.contains([<Button>yes</Button>, <Button>no</Button>]))\n    })\n})\n"
  },
  {
    "path": "ui-tests/QuickInfo.test.tsx",
    "content": "import { mount, shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport * as os from \"os\"\n\nimport {\n    QuickInfoDocumentation,\n    QuickInfoTitle,\n    Title,\n} from \"./../browser/src/UI/components/QuickInfo\"\n\ndescribe(\"<QuickInfo />\", () => {\n    it(\"renders a shallow instance of the component\", () => {\n        const wrapper = shallow(<QuickInfoTitle />)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n        expect(wrapper.length).toEqual(1)\n    })\n\n    it(\"renders the correct text\", () => {\n        const wrapper = mount(<QuickInfoTitle text=\"test text\" />)\n        expect(wrapper.text()).toContain(\"test text\")\n    })\n\n    it(\"renders the documentation correctly\", () => {\n        const test = [\"line One\", \"line Two\", \"line Three\"].join(os.EOL)\n        const wrapper = shallow(<QuickInfoDocumentation text={test} />)\n        expect(wrapper.children()).toHaveLength(3)\n    })\n})\n"
  },
  {
    "path": "ui-tests/SessionManager.test.tsx",
    "content": "import * as path from \"path\"\n\nimport {\n    ISession,\n    SessionManager,\n    UpdatedOni,\n} from \"./../browser/src/Services/Sessions/SessionManager\"\n\nimport Oni from \"./mocks/Oni\"\nimport Sidebar from \"./mocks/Sidebar\"\n\njest.mock(\"./../browser/src/Services/Configuration/UserConfiguration\", () => ({\n    getUserConfigFolderPath: jest.fn().mockReturnValue(\"~/.config/oni\"),\n}))\n\ninterface IStore {\n    [key: string]: ISession\n}\n\nconst mockPersistentStore = {\n    _store: {} as IStore,\n    get(): Promise<{ [key: string]: ISession }> {\n        return new Promise((resolve, reject) => {\n            resolve(this._store || {})\n        })\n    },\n    set(obj: { [key: string]: any }) {\n        return new Promise(resolve => {\n            this._store = { ...this._store, ...obj }\n            resolve(null)\n        })\n    },\n    delete(key: string) {\n        delete this._store[key]\n        return new Promise(resolve => resolve(this._store))\n    },\n    has(key) {\n        return !!this._store[key]\n    },\n}\n\ndescribe(\"Session Manager Tests\", () => {\n    const persistentStore = mockPersistentStore\n    const oni = new Oni({})\n    const manager = new SessionManager(oni as UpdatedOni, new Sidebar(), persistentStore)\n\n    beforeEach(() => {\n        mockPersistentStore._store = {}\n    })\n\n    it(\"Should return the correct session directory\", () => {\n        expect(manager.sessionsDir).toMatch(path.join(\".config\", \"oni\", \"session\"))\n    })\n\n    it(\"should save a session in the persistentStore\", async () => {\n        await manager.persistSession(\"test-session\")\n        const session = await persistentStore.get()\n        expect(session).toBeTruthy()\n    })\n\n    it(\"should correctly delete a session\", async () => {\n        await manager.persistSession(\"test-session\")\n        const session = await persistentStore.get()\n        expect(session).toBeTruthy()\n        await manager.deleteSession(\"test-session\")\n        expect(session[\"test-session\"]).toBeFalsy()\n    })\n\n    it(\"should correctly update a session\", async () => {\n        await manager.persistSession(\"test-session\")\n        await manager.updateOniSession(\"test-session\", { newValue: 2 })\n        const session = await manager.getSessionFromStore(\"test-session\")\n        expect(session.newValue).toBe(2)\n    })\n})\n"
  },
  {
    "path": "ui-tests/Sessions.test.tsx",
    "content": "import { shallow, mount } from \"enzyme\"\nimport * as React from \"react\"\n\nimport { Sessions, Container } from \"./../browser/src/Services/Sessions/Sessions\"\nimport TextInputView from \"../browser/src/UI/components/LightweightText\"\n\nconst noop = () => ({})\n\njest.mock(\"./../browser/src/neovim/SharedNeovimInstance\", () => ({\n    getInstance: () => ({\n        bindToMenu: () => ({\n            setItems: jest.fn(),\n            onCursorMoved: {\n                subscribe: jest.fn(),\n            },\n        }),\n    }),\n}))\n\ndescribe(\"<Sessions />\", () => {\n    const sessions = [\n        {\n            name: \"test\",\n            id: \"test-1\",\n            file: \"/sessions/test.vim\",\n            directory: \"/sessions\",\n            updatedAt: null,\n            workspace: \"/workspace\",\n        },\n        {\n            name: \"testing\",\n            id: \"testing-2\",\n            file: \"/sessions/testing.vim\",\n            directory: \"/sessions\",\n            updatedAt: null,\n            workspace: \"/workspace\",\n        },\n    ]\n    it(\"should render without crashing\", () => {\n        const wrapper = shallow(\n            <Sessions\n                active\n                cancelCreating={noop}\n                createSession={noop}\n                persistSession={noop}\n                restoreSession={noop}\n                updateSession={noop}\n                getAllSessions={noop}\n                updateSelection={noop}\n                sessions={sessions}\n                creating={false}\n                selected={sessions[0]}\n                populateSessions={noop}\n            />,\n        )\n    })\n    it(\"should render no children if showAll is false\", () => {\n        const wrapper = shallow(\n            <Sessions\n                active\n                cancelCreating={noop}\n                createSession={noop}\n                persistSession={noop}\n                restoreSession={noop}\n                updateSession={noop}\n                getAllSessions={noop}\n                updateSelection={noop}\n                sessions={sessions}\n                creating={false}\n                selected={sessions[0]}\n                populateSessions={noop}\n            />,\n        )\n        wrapper.setState({ showAll: false })\n        const items = wrapper\n            .dive()\n            .find(\"ul\")\n            .children()\n        expect(items.length).toBe(0)\n    })\n\n    it(\"should render correct number of children if showAll is true\", () => {\n        const wrapper = mount(\n            <Sessions\n                active\n                cancelCreating={noop}\n                createSession={noop}\n                persistSession={noop}\n                restoreSession={noop}\n                updateSession={noop}\n                getAllSessions={noop}\n                updateSelection={noop}\n                sessions={sessions.slice(1)} // remove one session\n                creating={false}\n                selected={sessions[0]}\n                populateSessions={noop}\n            />,\n        )\n        wrapper.setState({ showAll: true })\n        const items = wrapper.find(\"ul\").children()\n        expect(items.length).toBe(3)\n    })\n\n    it(\"should render an input if creating is true\", () => {\n        const wrapper = mount(\n            <Sessions\n                active\n                cancelCreating={noop}\n                createSession={noop}\n                persistSession={noop}\n                restoreSession={noop}\n                updateSession={noop}\n                getAllSessions={noop}\n                updateSelection={noop}\n                sessions={sessions.slice(1)} // remove one session\n                creating={true}\n                selected={sessions[0]}\n                populateSessions={noop}\n            />,\n        )\n        const hasInput = wrapper.find(TextInputView).length\n\n        expect(hasInput).toBeTruthy()\n    })\n\n    it(\"should render no input if creating is false\", () => {\n        const wrapper = mount(\n            <Sessions\n                active\n                cancelCreating={noop}\n                createSession={noop}\n                persistSession={noop}\n                restoreSession={noop}\n                updateSession={noop}\n                getAllSessions={noop}\n                updateSelection={noop}\n                sessions={sessions.slice(1)}\n                creating={false}\n                selected={null}\n                populateSessions={noop}\n            />,\n        )\n        const hasInput = wrapper.find(TextInputView).length\n\n        expect(hasInput).toBeFalsy()\n    })\n\n    it(\"should empty message if there are no sessions\", () => {\n        const wrapper = mount(\n            <Sessions\n                active\n                cancelCreating={noop}\n                createSession={noop}\n                persistSession={noop}\n                restoreSession={noop}\n                updateSession={noop}\n                getAllSessions={noop}\n                updateSelection={noop}\n                sessions={[]}\n                creating={true}\n                selected={null}\n                populateSessions={noop}\n            />,\n        )\n        expect(wrapper.find(Container).length).toBe(1)\n        expect(wrapper.find(Container).text()).toBe(\"No Sessions Saved\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/SidebarStore.test.ts",
    "content": "import {\n    decreaseWidth,\n    increaseWidth,\n    sidebarReducer,\n} from \"./../browser/src/Services/Sidebar/SidebarStore\"\n\ndescribe(\"Change size function\", () => {\n    it(\"Should correctly return an increased size\", () => {\n        const newSize = increaseWidth(\"12em\", null)\n        expect(newSize).toBe(\"13em\")\n    })\n\n    it(\"Should correctly return an decreased size\", () => {\n        const newSize = decreaseWidth(\"12em\", null)\n        expect(newSize).toBe(\"11em\")\n    })\n\n    it(\"Should return the original size if passed an invalid value\", () => {\n        const newSize = increaseWidth(\"appleem\", \"15em\")\n        expect(newSize).toBe(\"15em\")\n    })\n    it(\"Should return the last value if the user input is too big\", () => {\n        const newSize = increaseWidth(\"50em\", \"15em\")\n        expect(newSize).toBe(\"50em\")\n    })\n\n    it(\"Should return the last value if the user input is too small\", () => {\n        const newSize = decreaseWidth(\"1em\", \"15em\")\n        expect(newSize).toBe(\"1em\")\n    })\n\n    it(\"Should decrease a value if at top limit\", () => {\n        const newSize = decreaseWidth(\"50em\", null)\n        expect(newSize).toBe(\"49em\")\n    })\n\n    it(\"Should increase a value if at bottom limit\", () => {\n        const newSize = increaseWidth(\"1em\", null)\n        expect(newSize).toBe(\"2em\")\n    })\n\n    it(\"Should use a default unit if the user passes an invalid unit value\", () => {\n        const newSize = decreaseWidth(\"15apples\", \"12em\")\n        expect(newSize).toBe(\"14em\")\n    })\n    it(\"Should use default unit if the value passed in does not have any units\", () => {\n        const newSize = increaseWidth(\"15\", \"11em\")\n        expect(newSize).toBe(\"16em\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/Tabs.test.tsx",
    "content": "import { mount, shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\njest.mock(\"../browser/src/Services/FileIcon\")\nimport { FileIcon } from \"../browser/src/Services/FileIcon\"\njest.mock(\"../browser/src/UI/components/Sneakable\")\nimport { Sneakable } from \"../browser/src/UI/components/Sneakable\"\n\nimport { Corner, getHighlightColor, Name, Tab, Tabs } from \"../browser/src/UI/components/Tabs\"\n\nconst MockFileIcon = FileIcon as jest.Mock<{}>\nconst MockSneakable = Sneakable as jest.Mock<Sneakable>\n\ndescribe(\"<Tabs /> Tests\", () => {\n    MockFileIcon.mockImplementation(() => ({ render: jest.fn() }))\n    MockSneakable.mockImplementation(props => ({\n        render: () => props.children,\n    }))\n\n    const testTheme: any = {\n        \"highlight.mode.normal.background\": \"green\",\n        \"highlight.mode.insert.background\": \"blue\",\n    }\n\n    const tabCloseFunction = jest.fn()\n    const tabSelectFunction = jest.fn()\n\n    const tab1 = {\n        id: 1,\n        name: \"test\",\n        description: \"a test tab\",\n        isSelected: true,\n        isDirty: true,\n        iconFileName: \"icon\",\n        highlightColor: \"#000\",\n    }\n\n    const tab2 = {\n        id: 2,\n        name: \"test\",\n        description: \"a test tab\",\n        isSelected: false,\n        isDirty: true,\n        iconFileName: \"icon\",\n        highlightColor: \"#000\",\n    }\n\n    const TabsContainingSingleTab = (\n        <Tabs\n            fontSize=\"1.2em\"\n            shouldShowHighlight\n            mode=\"normal\"\n            maxWidth=\"20em\"\n            height=\"2em\"\n            fontFamily=\"inherit\"\n            shouldWrap={false}\n            visible={true}\n            onTabClose={tabCloseFunction}\n            onTabSelect={tabSelectFunction}\n            tabs={[tab1]}\n        />\n    )\n\n    const TabsContainingTwoTabs = (\n        <Tabs\n            fontSize=\"1.2em\"\n            shouldShowHighlight\n            mode=\"normal\"\n            maxWidth=\"20em\"\n            height=\"2em\"\n            fontFamily=\"inherit\"\n            shouldWrap={false}\n            visible={true}\n            onTabClose={tabCloseFunction}\n            onTabSelect={tabSelectFunction}\n            tabs={[tab1, tab2]}\n        />\n    )\n\n    const TabsNotVisible = (\n        <Tabs\n            fontSize=\"1.2em\"\n            shouldShowHighlight\n            mode=\"normal\"\n            maxWidth=\"20em\"\n            height=\"2em\"\n            fontFamily=\"inherit\"\n            shouldWrap={false}\n            visible={false}\n            tabs={[tab1]}\n        />\n    )\n\n    const unfocusedTab = (\n        <Tabs\n            fontSize=\"1.2em\"\n            shouldShowHighlight={false}\n            mode=\"normal\"\n            maxWidth=\"20em\"\n            height=\"2em\"\n            fontFamily=\"inherit\"\n            shouldWrap={false}\n            visible={false}\n            tabs={[tab1]}\n        />\n    )\n\n    afterEach(() => {\n        tabCloseFunction.mockReset()\n        tabSelectFunction.mockReset()\n    })\n\n    it(\"renders without crashing\", () => {\n        const wrapper = shallow(TabsContainingSingleTab)\n        expect(wrapper.length).toEqual(1)\n    })\n\n    it(\"should match last known snapshot unless we make a change\", () => {\n        const wrapper = shallow(TabsContainingSingleTab)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n\n    it(\"should render the correct number of tabs\", () => {\n        expect(shallow(TabsContainingSingleTab).children().length).toEqual(1)\n        expect(shallow(TabsContainingTwoTabs).children().length).toEqual(2)\n    })\n\n    it(\"should not render if the visible prop is false\", () => {\n        const wrapper = shallow(TabsNotVisible)\n        expect(wrapper.getElement()).toBe(null)\n    })\n\n    it(\"should call onTabClose callback on tab close button click\", () => {\n        const wrapper = mount(TabsContainingSingleTab)\n        const clickedTab = wrapper.find(Tab)\n\n        wrapper\n            .find(Corner)\n            .last()\n            .simulate(\"click\")\n\n        expect(tabCloseFunction).toHaveBeenCalledWith(clickedTab.props().id)\n\n        wrapper.unmount()\n    })\n\n    it(\"should call onTabSelect callback on tab title click\", () => {\n        const wrapper = mount(TabsContainingTwoTabs)\n        const clickedTab = wrapper.find(Tab).last()\n\n        clickedTab.find(Name).simulate(\"mouseDown\", { button: 0 })\n        expect(tabSelectFunction).toHaveBeenCalledWith(clickedTab.props().id)\n\n        wrapper.unmount()\n    })\n\n    it(\"should call onTabClose callback on tab title middle click\", () => {\n        const wrapper = mount(TabsContainingTwoTabs)\n        const clickedTab = wrapper.find(Tab).first()\n\n        clickedTab.find(Name).simulate(\"mouseDown\", { button: 1 })\n        expect(tabCloseFunction).toHaveBeenCalledWith(clickedTab.props().id)\n\n        wrapper.unmount()\n    })\n\n    it(\"should call onTabSelect callback on tab file icon click\", () => {\n        const wrapper = mount(TabsContainingTwoTabs)\n        const clickedTab = wrapper.find(Tab).last()\n\n        clickedTab\n            .find(Corner)\n            .first()\n            .simulate(\"mouseDown\", { button: 0 })\n        expect(tabSelectFunction).toHaveBeenCalledWith(clickedTab.props().id)\n\n        wrapper.unmount()\n    })\n\n    it(\"should call onTabClose callback on tab file icon middle click\", () => {\n        const wrapper = mount(TabsContainingTwoTabs)\n        const clickedTab = wrapper.find(Tab).first()\n\n        clickedTab\n            .find(Corner)\n            .first()\n            .simulate(\"mouseDown\", { button: 1 })\n        expect(tabCloseFunction).toHaveBeenCalledWith(clickedTab.props().id)\n\n        wrapper.unmount()\n    })\n\n    it(\"should pass tab name as Sneakable tag property\", () => {\n        const wrapper = mount(TabsContainingSingleTab)\n        const tab = wrapper.find(Tab)\n        const sneakable = wrapper.find(Sneakable)\n\n        expect(sneakable.props().tag).toEqual(tab.props().name)\n\n        wrapper.unmount()\n    })\n\n    it(\"should call onTabSelect callback as Sneakable callback\", () => {\n        MockSneakable.mockImplementationOnce(props => {\n            props.callback()\n        })\n\n        const wrapper = mount(TabsContainingSingleTab)\n        const sneakableTab = wrapper.find(Tab)\n\n        expect(tabSelectFunction).toHaveBeenCalledWith(sneakableTab.props().id)\n\n        wrapper.unmount()\n    })\n\n    it(\"should pass tab icon file name as FileIcon fileName property \", () => {\n        const wrapper = mount(TabsContainingSingleTab)\n        const tab = wrapper.find(Tab)\n        const fileIcon = wrapper.find(FileIcon)\n\n        expect(fileIcon.props().fileName).toEqual(tab.props().iconFileName)\n\n        wrapper.unmount()\n    })\n\n    it(\"should have a transparent border if not selected\", () => {\n        const highlight = getHighlightColor({\n            theme: testTheme,\n            isSelected: false,\n            shouldShowHighlight: true,\n            mode: \"normal\",\n        })\n        expect(highlight).toBe(\"transparent\")\n    })\n\n    it(\"should highlight the active tab with the mode color\", () => {\n        const highlight = getHighlightColor({\n            theme: testTheme,\n            isSelected: true,\n            shouldShowHighlight: true,\n            mode: \"normal\",\n        })\n        expect(highlight).toBe(\"green\")\n    })\n\n    it(\"should highlight the active tab with the normal mode color if the mode is a commandline mode\", () => {\n        const highlight = getHighlightColor({\n            theme: testTheme,\n            isSelected: true,\n            shouldShowHighlight: true,\n            mode: \"cmdline_normal\",\n        })\n\n        expect(highlight).toBe(\"green\")\n    })\n\n    it(\"should highlight the active tab with the normal mode color if the mode is in showmatch mode\", () => {\n        const highlight = getHighlightColor({\n            theme: testTheme,\n            isSelected: true,\n            shouldShowHighlight: true,\n            mode: \"showmatch\",\n        })\n\n        expect(highlight).toBe(\"blue\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/Text.test.tsx",
    "content": "import * as React from \"react\"\nimport { shallow } from \"enzyme\"\n\nimport { SelectedText, Text } from \"./../browser/src/UI/components/Text\"\n\ndescribe(\"<Text/SelectedText />\", () => {\n    it(\"Text component should match the last snapshot on record\", () => {\n        const wrapper = shallow(<Text text=\"Test\" />)\n        expect(wrapper).toMatchSnapshot()\n    })\n    it(\"SelectedText component should match the last snapshot on record\", () => {\n        const wrapper = shallow(<SelectedText text=\"Test\" />)\n        expect(wrapper).toMatchSnapshot()\n    })\n})\n"
  },
  {
    "path": "ui-tests/TokenScorer.test.ts",
    "content": "import { TokenScorer } from \"./../browser/src/Services/SyntaxHighlighting/TokenScorer\"\nimport { TokenColor } from \"./../browser/src/Services/TokenColors\"\n\ndescribe(\"TokenScorer Tests\", () => {\n    const ranker = new TokenScorer()\n    const theme: TokenColor[] = [\n        {\n            scope: \"entity\",\n            settings: {\n                foreground: \"blue\",\n                background: \"red\",\n                fontStyle: \"italic\",\n            },\n        },\n        {\n            scope: \"entity.name\",\n            settings: {\n                foreground: \"blue\",\n                background: \"red\",\n                fontStyle: \"italic\",\n            },\n        },\n        {\n            scope: \"entity.name.interface\",\n            settings: {\n                foreground: \"blue\",\n                background: \"red\",\n                fontStyle: \"italic\",\n            },\n        },\n        {\n            scope: \"entity.name.interface.golang\",\n            settings: {\n                foreground: \"blue\",\n                background: \"red\",\n                fontStyle: \"italic\",\n            },\n        },\n    ]\n    it(\"should correctly rank tokens based on how deep in the syntax tree they are\", () => {\n        const scopes = [\"entity.name\", \"entity.name.interface\", \"entity.name.interface.golang\"]\n        const highest = ranker.rankTokenScopes(scopes, theme)\n        expect(highest).toEqual({\n            scope: \"entity.name.interface.golang\",\n            settings: {\n                foreground: \"blue\",\n                background: \"red\",\n                fontStyle: \"italic\",\n            },\n        })\n    })\n\n    it(\"should only return a token that is included in the theme aka one that can be highlighted\", () => {\n        const scopes = [\n            \"entity.name\",\n            \"entity.name.interface\",\n            \"entity.name.interface.golang\",\n            \"item.class.component.element.object\",\n        ]\n        const highest = ranker.rankTokenScopes(scopes, theme)\n        expect(highest.scope).toBe(\"entity.name.interface.golang\")\n    })\n\n    it('should correctly prioritise fields with higher scope priorities like \"support\" ', () => {\n        const scopes = [\n            \"entity.name\",\n            \"entity.name.interface\",\n            \"entity.name.interface.golang\",\n            \"support.class.component.element\",\n        ]\n        const supportTheme: TokenColor[] = [\n            ...theme,\n            {\n                scope: \"support.class.component.element\",\n                settings: {\n                    foreground: \"blue\",\n                    background: \"red\",\n                    fontStyle: \"italic\",\n                },\n            },\n        ]\n\n        const highest = ranker.rankTokenScopes(scopes, supportTheme)\n        expect(highest).toEqual({\n            scope: \"support.class.component.element\",\n            settings: {\n                foreground: \"blue\",\n                background: \"red\",\n                fontStyle: \"italic\",\n            },\n        })\n    })\n\n    it(\"should return null if none of the scopes it is passed have any matches\", () => {\n        const highest = ranker.rankTokenScopes([\"testing.failure\"], theme)\n        expect(highest).toBeFalsy()\n    })\n\n    it(\"should ignore banned scopes like meta\", () => {\n        const highest = ranker.rankTokenScopes(\n            [\"meta.long.token.name\", \"source.other.long.name\"],\n            theme,\n        )\n        expect(highest).toBeFalsy()\n    })\n})\n"
  },
  {
    "path": "ui-tests/TokenThemeProvider.test.tsx",
    "content": "import * as React from \"react\"\nimport { mount } from \"enzyme\"\nimport \"jest-styled-components\"\n\nimport TokenThemeProvider from \"./../browser/src/Services/SyntaxHighlighting/TokenThemeProvider\"\nimport { TokenColor } from \"./../browser/src/Services/TokenColors\"\nimport styled, { css } from \"./../browser/src/UI/components/common\"\n\nconst tokenColors: TokenColor[] = [\n    {\n        scope: \"string.quoted\",\n        settings: {\n            foreground: \"green\",\n            background: \"blue\",\n            fontStyle: \"bold italic\",\n        },\n    },\n    {\n        scope: \"entity.name.struct\",\n        settings: {\n            foreground: \"rebeccapurple\",\n            background: \"orange\",\n            fontStyle: \"italic\",\n        },\n    },\n]\n\nconst TestComponent = styled<{ tokenStyles: any }, \"div\">(\"div\")`\n    ${p => p.tokenStyles};\n`\n\ndescribe(\"<TokenThemeProvider />\", () => {\n    const theme = {\n        \"editor.background\": \"black\",\n        \"editor.foreground\": \"white\",\n        \"menu.background\": \"green\",\n        \"menu.foreground\": \"grey\",\n    }\n\n    const component = (\n        <TokenThemeProvider\n            theme={theme}\n            tokenColors={tokenColors}\n            render={props => (\n                <TestComponent tokenStyles={props.styles}>\n                    <span className=\"string-quoted\">test text</span>\n                </TestComponent>\n            )}\n        />\n    )\n\n    it(\"should render without crashing\", () => {\n        const wrapper = mount(component)\n        expect(wrapper.length).toBe(1)\n    })\n\n    test.each`\n      className                | cssRule         | result\n      ${\".string-quoted\"}      | ${\"color\"}      | ${\"green\"}\n      ${\".string-quoted\"}      | ${\"font-style\"} | ${\"italic\"}\n      ${\".string-quoted\"}      | ${\"font-weight\"}| ${\"bold\"}\n      ${\".entity-name-struct\"} | ${\"color\"}      | ${\"rebeccapurple\"}\n      ${\".entity-name-struct\"} | ${\"font-style\"} | ${\"italic\"}\n      ${\".entity-name-struct\"} | ${\"font-weight\"}| ${undefined}\n    `(\n        \"the TokenThemeProvider returns a nested class rule with a style of $cssRule with a value of $result for $className\",\n        ({ cssRule, result, className }) => {\n            const wrapper = mount(component)\n            expect(wrapper.find(TestComponent)).toHaveStyleRule(cssRule, result, {\n                modifier: className,\n            })\n        },\n    )\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/Help.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport * as React from \"react\"\nimport Help, { Description } from \"./../../browser/src/UI/components/VersionControl/Help\"\n\ndescribe(\"<Help />\", () => {\n    it(\"Should render without crashing\", () => {\n        const wrapper = shallow(<Help />)\n        expect(wrapper.length).toBe(1)\n    })\n    it(\"Should show correct number of commands\", () => {\n        const wrapper = shallow(<Help />)\n        expect(wrapper.find(Description).length).toBeGreaterThan(3)\n    })\n    it(\"Should show correct first command\", () => {\n        const wrapper = shallow(<Help />)\n        const commandText = wrapper\n            .find(Description)\n            .at(0)\n            .dive()\n            .text()\n        expect(commandText).toMatch(/Open the currently selected file/)\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlCommits.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport * as React from \"react\"\n\nimport { DefaultLogFields } from \"../../browser/src/Services/VersionControl/VersionControlProvider\"\nimport VCSCommits, { ListItem } from \"./../../browser/src/UI/components/VersionControl/Commits\"\n\ndescribe(\"<VCSCommits />\", () => {\n    const fakeCommits: DefaultLogFields[] = [\n        {\n            date: null,\n            message: \"test 2\",\n            author_email: \"test@test.com\",\n            author_name: \"test\",\n            hash: \"FG45755\",\n        },\n        {\n            message: \"test\",\n            date: null,\n            author_name: \"john\",\n            author_email: \"john@test.com\",\n            hash: \"FG11111\",\n        },\n    ]\n    it(\"it renders without crashing\", () => {\n        const wrapper = shallow(\n            <VCSCommits\n                visibility\n                onClick={() => null}\n                toggleVisibility={() => null}\n                commits={fakeCommits}\n                selectedId=\"FG11111\"\n                titleId=\"Recent Commits\"\n            />,\n        )\n        expect(wrapper.length).toBe(1)\n    })\n\n    it(\"Should render the correct number of items for commits\", () => {\n        const wrapper = shallow(\n            <VCSCommits\n                visibility\n                onClick={() => null}\n                toggleVisibility={() => null}\n                commits={fakeCommits}\n                selectedId=\"FG11111\"\n                titleId=\"Recent Commits\"\n            />,\n        )\n        expect(wrapper.find(ListItem).length).toBe(2)\n    })\n\n    it(\"Should render no commits if visibility is false\", () => {\n        const wrapper = shallow(\n            <VCSCommits\n                visibility={false}\n                onClick={() => null}\n                toggleVisibility={() => null}\n                commits={fakeCommits}\n                selectedId=\"FG11111\"\n                titleId=\"Recent Commits\"\n            />,\n        )\n        expect(wrapper.find(ListItem).length).toBe(0)\n    })\n\n    it(\"Should not render items if there are no commits\", () => {\n        const wrapper = shallow(\n            <VCSCommits\n                visibility={false}\n                onClick={() => null}\n                toggleVisibility={() => null}\n                commits={[]}\n                selectedId=\"FG11111\"\n                titleId=\"Recent Commits\"\n            />,\n        )\n        expect(wrapper.find(ListItem).length).toBe(0)\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlComponents.test.tsx",
    "content": "import { mount, shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport Octicon from \"./../../browser/src/UI/components/Octicon\"\n\nimport {\n    Branch,\n    BranchNameContainer,\n} from \"./../../browser/src/UI/components/VersionControl/Branch\"\n\ndescribe(\"<Branch />\", () => {\n    const diff = {\n        insertions: 2,\n        deletions: 8,\n        files: null,\n    }\n\n    it(\"Should render without crashing\", () => {\n        const wrapper = shallow(<Branch branch=\"test-branch\" diff={diff} />)\n        expect(wrapper.length).toEqual(1)\n    })\n\n    it(\"Should render the correct branch name\", () => {\n        const wrapper = shallow(<Branch branch=\"test-branch\" diff={diff} />)\n        const name = wrapper\n            .find(BranchNameContainer)\n            .dive()\n            .text()\n        expect(name).toBe(\"test-branch < />\")\n    })\n    it(\"should match last known snapshot unless we make a change\", () => {\n        const wrapper = shallow(<Branch branch=\"test-branch\" diff={diff} />)\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n\n    it(\"Should show the correct number of additions\", () => {\n        const wrapper = mount(<Branch branch=\"test-branch\" diff={diff} />)\n        const additions = wrapper.find(\"[data-test='addition-2']\")\n        expect(additions.find(\"span\").text()).toEqual(\"2\")\n    })\n\n    it(\"Should show the correct number of deletions\", () => {\n        const wrapper = mount(<Branch branch=\"test-branch\" diff={diff} />)\n        const deletions = wrapper.find(\"[data-test='deletion-8']\")\n        expect(deletions.find(\"span\").text()).toEqual(\"8\")\n    })\n\n    it(\"should render the correct icon for additions\", () => {\n        const wrapper = mount(<Branch branch=\"test-branch\" diff={diff} />)\n        const hasAdded = wrapper.contains(<Octicon name=\"diff-added\" />)\n        expect(hasAdded).toBe(true)\n    })\n\n    it(\"should render the correct icon for deletions\", () => {\n        const wrapper = mount(<Branch branch=\"test-branch\" diff={diff} />)\n        const hasDeleted = wrapper.contains(<Octicon name=\"diff-removed\" />)\n        expect(hasDeleted).toBe(true)\n    })\n\n    it(\"Should not render an icon if there were no insertions\", () => {\n        const wrapper = mount(<Branch branch=\"test-branch\" diff={{ ...diff, insertions: 0 }} />)\n        const icon = wrapper.contains(<Octicon name=\"diff-added\" />)\n        expect(icon).toBe(false)\n    })\n\n    it(\"Should not render an icon if there were no deletions\", () => {\n        const wrapper = mount(<Branch branch=\"test-branch\" diff={{ ...diff, deletions: 0 }} />)\n        const icon = wrapper.contains(<Octicon name=\"diff-removed\" />)\n        expect(icon).toBe(false)\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlManager.test.tsx",
    "content": "import * as Oni from \"oni-api\"\nimport { Event } from \"oni-types\"\nimport * as React from \"react\"\n\nimport { Branch } from \"../../browser/src/UI/components/VersionControl/Branch\"\nimport {\n    VersionControlManager,\n    VersionControlProvider,\n} from \"./../../browser/src/Services/VersionControl\"\n\nimport MockOni from \"../mocks/Oni\"\nimport { mockStatusBarHide, mockStatusBarSetContents } from \"./../mocks/Statusbar\"\nimport MockNotifications from \"./../mocks/Notifications\"\nimport MockSidebar from \"./../mocks/Sidebar\"\n\njest.unmock(\"lodash\")\n\nconst makePromise = (arg?: any) => Promise.resolve(arg)\n\nconst provider: VersionControlProvider = {\n    name: \"svn\",\n    onFileStatusChanged: new Event(),\n    onBranchChanged: new Event(),\n    onPluginActivated: new Event(),\n    onPluginDeactivated: new Event(),\n    onStagedFilesChanged: new Event(),\n    isActivated: true,\n    fetchBranchFromRemote: () => null,\n    stageFile: () => null,\n    changeBranch: () => null,\n    getLocalBranches: () => makePromise([\"branch1\", \"branch2\"]),\n    canHandleWorkspace: () => makePromise(true),\n    getDiff: () => makePromise({}),\n    activate: () => null,\n    deactivate: () => null,\n    getStatus: () => makePromise({}),\n    getRoot: () => makePromise(\"/test/dir\"),\n    getBranch: () => makePromise(\"local\"),\n}\n\ndescribe(\"Version Control Manager tests\", () => {\n    let vcsManager: VersionControlManager\n    beforeEach(() => {\n        vcsManager = new VersionControlManager(\n            new MockOni(),\n            new MockSidebar(),\n            new MockNotifications(),\n        )\n        vcsManager.registerProvider(provider)\n    })\n\n    it(\"Should register a vcs provider\", () => {\n        expect(vcsManager.providers.size).toBe(1)\n    })\n\n    it(\"Should register the provider details\", () => {\n        expect(vcsManager.activeProvider.name).toBe(\"svn\")\n    })\n\n    it(\"should correctly deregister a provider\", () => {\n        vcsManager.deactivateProvider()\n        expect(vcsManager.activeProvider).toBeFalsy()\n    })\n\n    it(\"Should correctly hide the status bar item if the dir cannot handle the workspace\", async () => {\n        provider.canHandleWorkspace = async () => makePromise(false)\n        await vcsManager.registerProvider(provider)\n        expect(mockStatusBarHide.mock.calls.length).toBe(1)\n    })\n\n    it(\"should return the correct branch\", async () => {\n        const branch = await provider.getBranch()\n        expect(branch).toBe(\"local\")\n    })\n\n    it(\"Should return the correct local branches\", async () => {\n        const localBranches = await provider.getLocalBranches()\n        expect(localBranches).toEqual(expect.arrayContaining([\"branch1\", \"branch2\"]))\n    })\n\n    it(\"should set the contents of the statusbar correctly\", () => {\n        const branch = <Branch diff={{} as any} branch=\"local\" />\n        expect(mockStatusBarSetContents.mock.calls[0][0]).toEqual(branch)\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlPane.test.tsx",
    "content": "import * as Oni from \"oni-api\"\nimport { Event } from \"oni-types\"\n\nimport { VersionControlProvider } from \"./../../browser/src/Services/VersionControl\"\nimport VersionControlPane from \"./../../browser/src/Services/VersionControl/VersionControlPane\"\nimport store, {\n    DefaultState,\n    VersionControlState,\n} from \"./../../browser/src/Services/VersionControl/VersionControlStore\"\n\nimport MockOni from \"./../mocks/Oni\"\nimport MockSidebar from \"./../mocks/Sidebar\"\n\njest.mock(\"lodash/capitalize\", (str: string) => str)\njest.mock(\n    \"./../../browser/src/Services/VersionControl/VersionControlView\",\n    () => \"VersionControlView\",\n)\n\nconst makePromise = (arg?: any) => Promise.resolve(arg)\n\nconst provider: VersionControlProvider = {\n    name: \"git\",\n    onFileStatusChanged: new Event(),\n    onBranchChanged: new Event(),\n    onPluginActivated: new Event(),\n    onPluginDeactivated: new Event(),\n    onStagedFilesChanged: new Event(),\n    isActivated: true,\n    fetchBranchFromRemote: () => null,\n    stageFile: () => null,\n    changeBranch: () => null,\n    getLocalBranches: () => makePromise([\"branch1\", \"branch2\"]),\n    canHandleWorkspace: () => makePromise(true),\n    getDiff: () => makePromise({}),\n    activate: () => null,\n    deactivate: () => null,\n    getStatus: () =>\n        makePromise({\n            currentBranch: \"master\",\n        }),\n    getRoot: () => makePromise(\"/test/dir\"),\n    getBranch: () => makePromise(\"local\"),\n}\n\ndescribe(\"Version Control pane tests\", () => {\n    const mockSidebar = new MockSidebar()\n    const vcsStore = store\n    const vcsPane = new VersionControlPane(\n        new MockOni(),\n        provider,\n        args => null,\n        mockSidebar,\n        store,\n    )\n\n    it(\"Should create a new version control pane\", () => {\n        expect(vcsPane.id).toBe(\"oni.sidebar.vcs\")\n    })\n\n    it(\"get status should return the value expected\", async () => {\n        const result = await vcsPane.getStatus()\n        if (result) {\n            expect(result.currentBranch).toEqual(\"master\")\n        }\n    })\n    it(\"Correctly update the store\", async () => {\n        await vcsPane.getStatus()\n        const state = store.getState()\n        expect(state.status.currentBranch).toBe(\"master\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlSectionTitle.test.tsx",
    "content": "import * as React from \"react\"\nimport { shallow } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\n\nimport VersionControlTitle, { Title } from \"./../../browser/src/UI/components/SectionTitle\"\n\ndescribe(\"<VersionControlTitle />\", () => {\n    it(\"correctly renders without crashing\", () => {\n        const wrapper = shallow(\n            <VersionControlTitle\n                active\n                isSelected\n                title=\"test\"\n                onClick={() => ({})}\n                testId=\"test\"\n            />,\n        )\n\n        expect(wrapper.length).toBe(1)\n    })\n\n    it(\"should render the correct title\", () => {\n        const wrapper = shallow(\n            <VersionControlTitle\n                active\n                isSelected\n                title=\"test\"\n                onClick={() => ({})}\n                testId=\"test\"\n            />,\n        )\n            .dive()\n            .find(Title)\n            .dive()\n        expect(wrapper.text()).toBe(\"TEST\")\n    })\n\n    it(\"Should correctly show the count if present\", () => {\n        const wrapper = shallow(\n            <VersionControlTitle\n                active\n                isSelected\n                title=\"test\"\n                onClick={() => ({})}\n                count={5}\n                testId=\"test\"\n            />,\n        )\n\n        expect(\n            wrapper\n                .dive()\n                .find(\"strong\")\n                .text(),\n        ).toBe(\"5\")\n    })\n\n    it(\"should match last known snapshot\", () => {\n        const wrapper = shallow(\n            <VersionControlTitle\n                active\n                isSelected\n                title=\"test\"\n                onClick={() => ({})}\n                testId=\"test\"\n            />,\n        )\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlStore.test.ts",
    "content": "import { Store } from \"redux\"\n\nimport vcsStore from \"./../../browser/src/Services/VersionControl/VersionControlStore\"\n\ndescribe(\"Version control reducer test\", () => {\n    it(\"Should correctly update the store with the vcs status\", () => {\n        const status = {\n            currentBranch: \"master\",\n            staged: [\"/test.txt\"],\n            conflicted: [],\n            created: [],\n            modified: [],\n            remoteTrackingBranch: \"origin/master\",\n            deleted: [],\n            untracked: [],\n            ahead: null,\n            behind: null,\n        }\n\n        vcsStore.dispatch({ type: \"STATUS\", payload: { status } })\n        const state = vcsStore.getState()\n        expect(state.status.currentBranch).toBe(\"master\")\n        expect(state.status.staged[0]).toBe(\"/test.txt\")\n    })\n\n    it(\"should correctly update the focus state\", () => {\n        vcsStore.dispatch({ type: \"ENTER\" })\n        const state = vcsStore.getState()\n        expect(state.hasFocus).toBe(true)\n    })\n\n    it(\"Should correctly register an error\", () => {\n        vcsStore.dispatch({ type: \"ERROR\" })\n        const state = vcsStore.getState()\n        expect(state.hasError).toBe(true)\n    })\n\n    it(\"Should correctly set the selected item\", () => {\n        vcsStore.dispatch({ type: \"SELECT\", payload: { selected: \"/test.txt\" } })\n        const state = vcsStore.getState()\n        expect(state.selected).toBe(\"/test.txt\")\n    })\n\n    it(\"Should correctly set the commit active on commit start\", () => {\n        vcsStore.dispatch({ type: \"COMMIT_START\", payload: { files: [\"/test.txt\"] } })\n        const state = vcsStore.getState()\n        expect(state.commit.active).toBe(true)\n    })\n\n    it(\"Should correctly set the commit active to false on commit cancel\", () => {\n        vcsStore.dispatch({ type: \"COMMIT_CANCEL\" })\n        const state = vcsStore.getState()\n        expect(state.commit.active).toBe(false)\n    })\n\n    it(\"Should set commit active to false on commit success and add the commit\", () => {\n        vcsStore.dispatch({ type: \"COMMIT_START\", payload: { files: [\"/test.txt\"] } })\n        vcsStore.dispatch({\n            type: \"UPDATE_COMMIT_MESSAGE\",\n            payload: { message: [\"commit message\"] },\n        })\n        vcsStore.dispatch({ type: \"COMMIT_SUCCESS\", payload: { commit: { branch: \"test\" } } })\n        const state = vcsStore.getState()\n        expect(state.commit.active).toBe(false)\n        expect(state.commit.previousCommits[0].message).toBe(\"commit message\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/VersionControlView.test.tsx",
    "content": "import { shallow, mount } from \"enzyme\"\nimport { shallowToJson } from \"enzyme-to-json\"\nimport * as React from \"react\"\n\nimport { SectionTitle, Title } from \"./../../browser/src/UI/components/SectionTitle\"\n\nimport {\n    DefaultState,\n    VersionControlState,\n} from \"./../../browser/src/Services/VersionControl/VersionControlStore\"\nimport { VersionControlView } from \"./../../browser/src/Services/VersionControl/VersionControlView\"\nimport CommitMessage, {\n    Explainer,\n} from \"./../../browser/src/UI/components/VersionControl/CommitMessage\"\nimport Commits from \"./../../browser/src/UI/components/VersionControl/Commits\"\nimport Help from \"./../../browser/src/UI/components/VersionControl/Help\"\nimport Staged, { LoadingHandler } from \"./../../browser/src/UI/components/VersionControl/Staged\"\nimport VersionControlStatus from \"./../../browser/src/UI/components/VersionControl/Status\"\n\nconst noop = jest.fn()\n\njest.mock(\"./../../browser/src/neovim/SharedNeovimInstance\", () => ({\n    getInstance: () => ({\n        bindToMenu: () => ({\n            setItems: jest.fn(),\n            onCursorMoved: {\n                subscribe: jest.fn(),\n            },\n        }),\n    }),\n}))\n\nconst IDs: any = {\n    modified: \"modified\",\n    commits: \"commits\",\n    untracked: \"untracked\",\n    staged: \"staged\",\n    commitAll: \"commit_all\",\n}\n\nconst makePromise = (arg?: any) => Promise.resolve(arg)\n\njest.mock(\"../../browser/src/UI/components/Sneakable\", () => {\n    const React = require(\"react\") // tslint:disable-line\n    return { Sneakable: () => <div /> }\n})\n\ndescribe(\"<VersionControlView />\", () => {\n    const state = { ...DefaultState, activated: true, hasFocus: true }\n    const container = shallow(\n        <VersionControlView\n            {...state}\n            commit={noop}\n            filesToCommit={[\"/test.txt\"]}\n            setLoading={noop}\n            IDs={IDs}\n            showHelp={true}\n            committing={false}\n            cancelCommit={noop}\n            updateCommitMessage={noop}\n            commits={[]}\n            message={[]}\n            selectedItem={null}\n            loadingSection={null}\n            loading={false}\n            getStatus={() => makePromise({})}\n        />,\n    )\n    it(\"renders without crashing\", () => {\n        expect(container.length).toBe(1)\n    })\n\n    it(\"should render an untracked, staged and modified section\", () => {\n        const container = mount(\n            <VersionControlView\n                {...state}\n                commit={noop}\n                setLoading={noop}\n                filesToCommit={[\"/test.txt\"]}\n                IDs={IDs}\n                loading={false}\n                loadingSection={null}\n                showHelp={false}\n                committing={false}\n                cancelCommit={noop}\n                updateCommitMessage={noop}\n                commits={[]}\n                message={[]}\n                selectedItem={null}\n                getStatus={() => makePromise({})}\n            />,\n        )\n        const staged = container.find(Staged)\n        expect(staged.length).toBe(1)\n        const untrackedAndModified = container.find(VersionControlStatus)\n        expect(untrackedAndModified.length).toBe(2)\n        const commits = container.find(Commits)\n        expect(commits.length).toBe(1)\n    })\n\n    it(\"shouldn't show a section if it has no content\", () => {\n        const wrapper = shallow(\n            <VersionControlStatus\n                onClick={noop}\n                toggleVisibility={noop}\n                visibility={true}\n                titleId=\"modified\"\n                selectedId=\"file1\"\n                icon=\"M\"\n                files={null}\n            />,\n        )\n        expect(wrapper.find(SectionTitle).length).toBe(0)\n    })\n\n    it(\"should match the last recorded snapshot unless a change was made\", () => {\n        const wrapper = shallow(\n            <VersionControlStatus\n                titleId=\"modified\"\n                visibility={true}\n                toggleVisibility={noop}\n                onClick={noop}\n                selectedId=\"file1\"\n                icon=\"M\"\n                files={[\"test1\", \"test2\"]}\n            />,\n        )\n        expect(shallowToJson(wrapper)).toMatchSnapshot()\n    })\n\n    it(\"Should render only the title if not visible\", () => {\n        const wrapper = mount(\n            <Staged\n                files={[]}\n                filesToCommit={[\"test.txt\"]}\n                titleId=\"staged\"\n                visible={false}\n                handleCommitOne={jest.fn()}\n                handleCommitMessage={jest.fn()}\n                handleCommitCancel={jest.fn()}\n                handleCommitAll={jest.fn()}\n                toggleVisibility={noop}\n                selectedId=\"commit_all\"\n                icon=\"cross\"\n                loading={false}\n                handleSelection={noop}\n            />,\n        )\n\n        expect(wrapper.find(SectionTitle).length).toBe(1)\n        expect(wrapper.children.length).toBe(1)\n    })\n\n    it(\"should render a loading spinner if loading is true\", () => {\n        const wrapper = mount(\n            <Staged\n                files={[\"test.txt\"]}\n                filesToCommit={[\"test.txt\"]}\n                selectedToCommit={() => false}\n                titleId=\"staged\"\n                visible\n                handleCommitOne={jest.fn()}\n                handleCommitMessage={jest.fn()}\n                handleCommitCancel={jest.fn()}\n                handleCommitAll={jest.fn()}\n                toggleVisibility={noop}\n                selectedId=\"commit_all\"\n                icon=\"cross\"\n                loading\n                handleSelection={noop}\n            />,\n        )\n        expect(wrapper.find(LoadingHandler).length).toBe(2)\n    })\n\n    it(\"should render an Input in place of the commit all explainer\", () => {\n        const wrapper = mount(\n            <Staged\n                visible\n                loading\n                icon=\"cross\"\n                titleId=\"staged\"\n                files={[\"test.txt\"]}\n                filesToCommit={[]}\n                selectedToCommit={() => true}\n                handleCommitOne={jest.fn()}\n                handleCommitMessage={jest.fn()}\n                handleCommitCancel={jest.fn()}\n                handleCommitAll={jest.fn()}\n                toggleVisibility={noop}\n                selectedId=\"commit_all\"\n                handleSelection={noop}\n            />,\n        )\n        expect(wrapper.find(CommitMessage).length).toBe(1)\n    })\n\n    it(\"should render help if show help is true\", () => {\n        expect(container.find(Help).length).toBe(1)\n    })\n\n    it(\"should render help prompt if show help is false\", () => {\n        container.setProps({ showHelp: false })\n        expect(\n            container\n                .find(Title)\n                .dive()\n                .text(),\n        ).toBe('To show help press \"?\"')\n    })\n})\n"
  },
  {
    "path": "ui-tests/VersionControl/__snapshots__/VersionControlComponents.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<Branch /> should match last known snapshot unless we make a change 1`] = `\n<styled.div>\n  <styled.span>\n    <OcticonByName\n      name=\"git-branch\"\n    />\n    <styled.span>\n      test-branch \n      <Component\n        deletions={8}\n        insertions={2}\n      />\n    </styled.span>\n  </styled.span>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/VersionControl/__snapshots__/VersionControlSectionTitle.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<VersionControlTitle /> should match last known snapshot 1`] = `\n<styled.div\n  data-test=\"test\"\n  isSelected={true}\n  onClick={[Function]}\n>\n  <Caret\n    active={true}\n  />\n  <styled.h4>\n    TEST\n  </styled.h4>\n  <strong />\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/VersionControl/__snapshots__/VersionControlView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<VersionControlView /> should match the last recorded snapshot unless a change was made 1`] = `\n<div>\n  <SidebarSectionTitle\n    active={true}\n    count={2}\n    isSelected={false}\n    onClick={[MockFunction]}\n    testId=\"modified-2\"\n    title=\"modified\"\n  />\n  <File\n    file=\"test1\"\n    icon=\"M\"\n    isSelected={false}\n    key=\"test1\"\n    onClick={[MockFunction]}\n  />\n  <File\n    file=\"test2\"\n    icon=\"M\"\n    isSelected={false}\n    key=\"test2\"\n    onClick={[MockFunction]}\n  />\n</div>\n`;\n"
  },
  {
    "path": "ui-tests/VersionControlBlameLayer.test.tsx",
    "content": "import { mount } from \"enzyme\"\nimport * as React from \"react\"\n\nimport { LayerContextWithCursor } from \"./../browser/src/Editor/NeovimEditor/NeovimBufferLayersView\"\nimport {\n    Blame,\n    BlameContainer,\n    IProps,\n    IState,\n} from \"./../browser/src/Services/VersionControl/VersionControlBlameLayer\"\n\njest.mock(\"react-transition-group\", () => {\n    const React = require(\"react\") // tslint:disable-line\n    // IMPORTANT: transition here implies a render props\n    const FakeTransition = jest.fn(({ children }) => children())\n    const FakeCSSTransition = jest.fn(\n        props => (props.in ? <FakeTransition>{props.children}</FakeTransition> : null),\n    )\n    return { CSSTransition: FakeCSSTransition, Transition: FakeTransition }\n})\n\ndescribe(\"<VersionControlBlameLayer />\", () => {\n    const blame = {\n        author: \"ernest hemmingway\",\n        author_mail: \"ernie@h.com\",\n        author_time: \"342423423424\",\n        author_tz: \"+ 100\",\n        committer: \"ernie\",\n        committer_mail: \"ernie@h.com\",\n        committer_time: \"342423423424\",\n        committer_tz: \"+ 100\",\n        filename: \"moby_dick.txt\",\n        hash: \"223423423442434234\",\n        line: { originalLine: \"1\", finalLine: \"1\", numberOfLines: \"1\" },\n        summary: \"the first paragraph\",\n    }\n    const getBlame = jest.fn().mockReturnValue(blame)\n    const context: LayerContextWithCursor = {\n        isActive: true,\n        windowId: 1,\n        fontPixelWidth: 3,\n        fontPixelHeight: 10,\n        cursorColumn: 4,\n        cursorLine: 30,\n        bufferToScreen: jest.fn(),\n        screenToPixel: jest.fn(),\n        bufferToPixel: jest.fn().mockReturnValue({\n            pixelX: 20,\n            pixelY: 20,\n        }),\n        dimensions: {\n            width: 100,\n            height: 100,\n            x: 0,\n            y: 0,\n        },\n        visibleLines: [\n            // Absolute line numbers\n            \"test string1\", // line 20\n            \"test string2\",\n            \"\",\n            \"test string4\",\n            \"test string5\",\n            \"test string6\",\n            \"test string7\",\n            \"test string8\",\n            \"test string9\",\n            \"test string10\",\n            \"test string11\",\n            \"cursor\", // line 22\n            \"test string13\",\n            \"test string14\",\n            \"test string15\",\n            \"test string16\",\n            \"test string17\",\n            \"test string18\",\n            \"test string19\",\n            \"test string20\", // line 40\n        ],\n        topBufferLine: 20,\n        bottomBufferLine: 40,\n    }\n    const cursorBufferLine = context.cursorLine + 1\n    const cursorScreenLine = cursorBufferLine - context.topBufferLine\n    const wrapper = mount<IProps, IState>(\n        <Blame\n            mode=\"auto\"\n            timeout={0}\n            {...context}\n            getBlame={getBlame}\n            setupCommand={jest.fn()}\n            cursorScreenLine={cursorScreenLine}\n            cursorBufferLine={cursorBufferLine}\n            currentLine={context.visibleLines[cursorScreenLine]}\n            fontFamily=\"arial\"\n        />,\n    )\n\n    const instance = wrapper.instance() as Blame\n\n    afterEach(() => {\n        wrapper.setProps({ ...context })\n    })\n\n    it(\"should render without crashing\", () => {\n        expect(wrapper.length).toBe(1)\n    })\n    it(\"should render the component if there is a blame present and show blame is true\", () => {\n        wrapper.setState({ showBlame: true, blame })\n        expect(wrapper.find(BlameContainer).length).toBe(1)\n    })\n    it(\"should render the correct message\", () => {\n        const text = wrapper.find(\"span\").text()\n        expect(text).toMatch(/the first paragraph/)\n    })\n    it(\"should return a formatted hash in the message\", () => {\n        const text = wrapper.find(\"span\").text()\n        expect(text).toMatch(/#2234/)\n    })\n    it(\"should correctly return a position if the component is able to fit\", () => {\n        const position = instance.calculatePosition(true)\n        expect(position).toEqual({ hide: false, top: 20, left: 20 })\n    })\n    it(\"should return a position even if can't fit BUT there is an available empty line\", () => {\n        const canFit = false\n        const position = instance.calculatePosition(canFit)\n        expect(position).toEqual({ hide: false, top: 20, left: 20 })\n    })\n    it(\"Should correctly determine if a line is out of bounds\", () => {\n        const outOfBounds = instance.isOutOfBounds(50, 10)\n        expect(outOfBounds).toBe(true)\n    })\n    it(\"should return false if no lines passed are out of bounds\", () => {\n        const outOfBounds = instance.isOutOfBounds(22, 24)\n        expect(outOfBounds).toBe(false)\n    })\n    it(\"should correctly truncate the blame text based on window width prop\", () => {\n        const expected = \"ernest hemmingway, 2 days ago, the first… #2234\"\n        wrapper.setProps({ dimensions: { width: 60, height: 100, x: 0, y: 0 } })\n        const { message, canFit, position } = instance.canFit()\n        expect(message).toEqual(expected)\n    })\n    it(\"should have the correct current line\", () => {\n        const line = wrapper.prop(\"currentLine\")\n        expect(line).toBe(\"cursor\")\n    })\n    it(\"should correctly identify the last empty line\", () => {\n        const { lastEmptyLine } = instance.getLastEmptyLine()\n        expect(lastEmptyLine).toBe(22) // aka the 3 item in the array\n    })\n})\n"
  },
  {
    "path": "ui-tests/VimNavigator.test.tsx",
    "content": "import * as React from \"react\"\nimport { shallow } from \"enzyme\"\n\nimport { VimNavigator } from \"../browser/src/UI/components/VimNavigator\"\n\ndescribe(\"<VimNavigator />\", () => {\n    let wrapper: any\n    let onSelectionChanged: jest.Mock\n\n    beforeEach(() => {\n        onSelectionChanged = jest.fn()\n        wrapper = shallow(\n            <VimNavigator\n                ids={[\"a\", \"b\"]}\n                active={false}\n                render={jest.fn()}\n                onSelectionChanged={onSelectionChanged}\n            />,\n        )\n    })\n\n    it(\"should have undefined idToSelect by default\", () => {\n        expect(wrapper.state().selectedId).toEqual(\"a\")\n        expect(wrapper.props().idToSelect).toBeUndefined()\n    })\n\n    it(\"should update selectedId and call onSelectionChanged when idToSelect changes\", () => {\n        wrapper.setProps({ idToSelect: \"b\" })\n\n        expect(wrapper.state().selectedId).toEqual(\"b\")\n        expect(onSelectionChanged).toHaveBeenCalledWith(\"b\")\n    })\n\n    it(\"should not call onSelectionChanged if idToSelect matches current selectedId\", () => {\n        wrapper.setProps({ idToSelect: \"a\" })\n\n        expect(wrapper.state().selectedId).toEqual(\"a\")\n        expect(onSelectionChanged).not.toHaveBeenCalled()\n    })\n})\n"
  },
  {
    "path": "ui-tests/WelcomeCommandsView.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport toJson from \"enzyme-to-json\"\n\nimport * as React from \"react\"\n\nimport {\n    WelcomeButton,\n    WelcomeCommandsView,\n} from \"./../browser/src/Editor/NeovimEditor/WelcomeBufferLayer\"\n\ndescribe(\"Welcome Layer test\", () => {\n    const buttons = [\n        \"button1\",\n        \"button2\",\n        \"button3\",\n        \"button4\",\n        \"button5\",\n        \"button6\",\n        \"button7\",\n        \"button8\",\n    ]\n\n    const restoreSession = jest.fn()\n    const executeCommand = jest.fn()\n\n    const commands = {\n        openFile: {\n            execute: jest.fn(),\n            command: \"button1\",\n        },\n        openTutor: {\n            execute: jest.fn(),\n            command: \"button2\",\n        },\n        openDocs: {\n            execute: jest.fn(),\n            command: \"button3\",\n        },\n        openConfig: {\n            execute: jest.fn(),\n            command: \"button4\",\n        },\n        openThemes: {\n            execute: jest.fn(),\n            command: \"button5\",\n        },\n        openWorkspaceFolder: {\n            execute: jest.fn(),\n            command: \"button6\",\n        },\n        commandPalette: {\n            execute: jest.fn(),\n            command: \"button7\",\n        },\n        commandline: {\n            execute: jest.fn(),\n            command: \"button8\",\n        },\n        restoreSession,\n    }\n\n    it(\"should render without crashing\", () => {\n        const wrapper = shallow(\n            <WelcomeCommandsView\n                selectedId=\"button1\"\n                active\n                commands={commands}\n                executeCommand={executeCommand}\n            />,\n        )\n        expect(wrapper.length).toBe(1)\n    })\n\n    it(\"should match last snapshot on record\", () => {\n        const wrapper = shallow(\n            <WelcomeCommandsView\n                selectedId=\"button1\"\n                active\n                commands={commands}\n                executeCommand={executeCommand}\n            />,\n        )\n        expect(toJson(wrapper)).toMatchSnapshot()\n    })\n    it(\"should have the correct number of buttons for each commands\", () => {\n        const wrapper = shallow(\n            <WelcomeCommandsView\n                selectedId=\"button1\"\n                active\n                commands={commands}\n                executeCommand={executeCommand}\n            />,\n        )\n        expect(wrapper.dive().find(WelcomeButton).length).toBe(8)\n    })\n})\n"
  },
  {
    "path": "ui-tests/WelcomeView.test.tsx",
    "content": "import { shallow } from \"enzyme\"\nimport toJson from \"enzyme-to-json\"\nimport { Event } from \"oni-types\"\nimport * as React from \"react\"\n\nimport {\n    WelcomeView,\n    WelcomeViewProps,\n    WelcomeViewState,\n    IWelcomeInputEvent,\n    SessionsList,\n    SectionItem,\n    SectionHeader,\n} from \"./../browser/src/Editor/NeovimEditor/WelcomeBufferLayer\"\n\ndescribe(\"<WelcomeView />\", () => {\n    const buttons = [\n        \"button1\",\n        \"button2\",\n        \"button3\",\n        \"button4\",\n        \"button5\",\n        \"button6\",\n        \"button7\",\n        \"button8\",\n    ]\n\n    const restoreSession = jest.fn()\n    const executeCommand = jest.fn()\n\n    const commands = {\n        openFile: {\n            execute: jest.fn(),\n            command: \"button1\",\n        },\n        openTutor: {\n            execute: jest.fn(),\n            command: \"button2\",\n        },\n        openDocs: {\n            execute: jest.fn(),\n            command: \"button3\",\n        },\n        openConfig: {\n            execute: jest.fn(),\n            command: \"button4\",\n        },\n        openThemes: {\n            execute: jest.fn(),\n            command: \"button5\",\n        },\n        openWorkspaceFolder: {\n            execute: jest.fn(),\n            command: \"button6\",\n        },\n        quickOpenShow: {\n            execute: jest.fn(),\n            command: \"button7\",\n        },\n        commandline: {\n            execute: jest.fn(),\n            command: \"button8\",\n        },\n        restoreSession,\n    }\n\n    const sessions = [\n        {\n            name: \"test\",\n            id: \"test-1\",\n            file: \"/test/dir\",\n            directory: \"/test/dir\",\n            workspace: \"/test/dir\",\n        },\n    ]\n\n    const inputEvent = new Event<IWelcomeInputEvent>(\"handleInputTestEvent\")\n    const getMetadata = async () => ({ version: \"1\" })\n\n    const ids = [...buttons, ...sessions.map(({ id }) => id)]\n    const wrapper = shallow<WelcomeViewProps, WelcomeViewState>(\n        <WelcomeView\n            active\n            ids={ids}\n            sessions={sessions}\n            commands={commands}\n            inputEvent={inputEvent}\n            getMetadata={getMetadata}\n            restoreSession={restoreSession}\n            sections={[buttons.length, sessions.length]}\n            executeCommand={executeCommand}\n        />,\n    )\n\n    it(\"Should render without crashing\", () => {\n        expect(wrapper.length).toBe(1)\n    })\n\n    it(\"should match its last snapshot\", () => {\n        expect(toJson(wrapper)).toMatchSnapshot()\n    })\n\n    it(\"should set the correct version\", () => {\n        expect(wrapper.state().version).toBe(\"1\")\n    })\n\n    it(\"should have the correct initial state\", () => {\n        expect(wrapper.state()).toEqual({ version: \"1\", currentIndex: 0, selectedId: \"button1\" })\n    })\n\n    it(\"should correctly update selection based on input\", () => {\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: 1, select: false })\n        expect(wrapper.state().selectedId).toBe(\"button2\")\n    })\n\n    it(\"should loop back to last button if user navigates upwards at the first button\", () => {\n        wrapper.setState({ currentIndex: 0, selectedId: \"button1\" })\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: -1, select: false })\n        expect(wrapper.state().currentIndex).toBe(ids.length - 1)\n        expect(wrapper.state().selectedId).toBe(\"test-1\")\n    })\n\n    it(\"should loop back to first button if user navigates downwards at the last button\", () => {\n        wrapper.setState({ currentIndex: ids.length - 1, selectedId: \"test-1\" })\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: 1, select: false })\n        expect(wrapper.state().currentIndex).toBe(0)\n        expect(wrapper.state().selectedId).toBe(\"button1\")\n    })\n\n    it(\"should trigger a command on enter event\", () => {\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: 0, select: true })\n        expect(commands.openFile.execute).toHaveBeenCalled()\n    })\n\n    it(\"should navigate right if horizontal is 1\", () => {\n        wrapper.setState({ currentIndex: 7, selectedId: \"button8\" })\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: 0, horizontal: 1, select: false })\n        expect(wrapper.state().currentIndex).toBe(8)\n        expect(wrapper.state().selectedId).toBe(\"test-1\")\n    })\n\n    it(\"should navigate left if horizontal is -1\", () => {\n        wrapper.setState({ currentIndex: ids.length - 1, selectedId: \"test-1\" })\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: 0, horizontal: -1, select: false })\n        expect(wrapper.state().currentIndex).toBe(0)\n        expect(wrapper.state().selectedId).toBe(\"button1\")\n    })\n\n    it(\"should call restore session if the selectedId is a session\", () => {\n        wrapper.setState({ currentIndex: ids.length - 1, selectedId: \"test-1\" })\n        const instance = wrapper.instance() as WelcomeView\n        instance.handleInput({ vertical: 0, horizontal: 0, select: true })\n        expect(restoreSession.mock.calls[0][0]).toBe(\"test\")\n    })\n\n    it(\"Should render a section header\", () => {\n        const headers = wrapper.dive().find(SectionHeader).length\n        expect(headers).toBe(1)\n    })\n\n    it(\"should render the place holder text if there are no sessions available\", () => {\n        wrapper.setProps({ sessions: [] })\n        const placeholder = wrapper\n            .find(SectionItem)\n            .dive()\n            .text()\n        expect(placeholder).toBe(\"No Sessions Available\")\n    })\n})\n"
  },
  {
    "path": "ui-tests/WindowTitleView.test.tsx",
    "content": "import * as React from \"react\"\nimport { shallow } from \"enzyme\"\n\nimport { WindowTitleView } from \"./../browser/src/UI/components/WindowTitle\"\n\ndescribe(\"<WindowTitleView />\", () => {\n    it(\"Text component should match the last snapshot on record\", () => {\n        const wrapper = shallow(<WindowTitleView title=\"Test Window\" visible={true} />)\n        expect(wrapper).toMatchSnapshot()\n    })\n    it(\"should only render if visible\", () => {\n        const wrapper = shallow(<WindowTitleView title=\"Test\" visible={false} />)\n        expect(wrapper.children().length).toBe(0)\n    })\n})\n"
  },
  {
    "path": "ui-tests/__snapshots__/BrowserView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<BrowserView /> Tests Should match the recent snapshot - unless an intentional change has occurred  1`] = `\n<styled.div\n  key=\"test2\"\n>\n  <styled.div>\n    <Component\n      icon=\"chevron-left\"\n      onClick={[Function]}\n    />\n    <Component\n      icon=\"chevron-right\"\n      onClick={[Function]}\n    />\n    <Component\n      icon=\"undo\"\n      onClick={[Function]}\n    />\n    <AddressBarView\n      onAddressChanged={[Function]}\n      url=\"test.com\"\n    />\n    <Component\n      icon=\"bug\"\n      onClick={[Function]}\n    />\n  </styled.div>\n  <styled.div>\n    <div\n      key=\"test\"\n      style={\n        Object {\n          \"bottom\": \"0px\",\n          \"left\": \"0px\",\n          \"position\": \"absolute\",\n          \"right\": \"0px\",\n          \"top\": \"0px\",\n        }\n      }\n    />\n  </styled.div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/BufferScrollBar.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<BufferScrollBar /> should match last recorded snapshot 1`] = `\n<styled.div\n  height={30}\n  key=\"1\"\n  onMouseDown={[Function]}\n>\n  <styled.div\n    height={25}\n    top={0}\n  />\n  <styled.div\n    color=\"yellow\"\n    height=\"2px\"\n    id=\"scrollbar-marker-element\"\n    key=\"1_yellow_4\"\n    top={4}\n  />\n  <styled.div\n    color=\"red\"\n    height=\"2px\"\n    id=\"scrollbar-marker-element\"\n    key=\"1_red_10\"\n    top={10}\n  />\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/CommandLine.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<Commandline /> should match last known snapshot unless we make a change 1`] = `\n<styled.div\n  className=\"command-line\"\n  visible={true}\n>\n  <styled.div\n    className=\"command-line-output\"\n    innerRef={[Function]}\n  >\n    :\n    <styled.span />\n    c\n    o\n    m\n    m\n    a\n    n\n    d\n    l\n    i\n    n\n    e\n     \n    t\n    e\n    s\n    t\n  </styled.div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/ErrorInfo.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<ErrorInfo /> Should match the last snapshot on record unless a purposeful change was made 1`] = `\n<styled.div\n  hasQuickInfo={true}\n>\n  <styled.div\n    key=\"5an error heretest0\"\n  >\n    <Component\n      color=\"yellow\"\n    />\n    <styled.span\n      data-id=\"diagnostic-message\"\n    >\n      an error here\n    </styled.span>\n  </styled.div>\n  <styled.div\n    key=\"5an error heretest1\"\n  >\n    <Component\n      color=\"yellow\"\n    />\n    <styled.span\n      data-id=\"diagnostic-message\"\n    >\n      an error here\n    </styled.span>\n  </styled.div>\n  <styled.div\n    key=\"5an error heretest2\"\n  >\n    <Component\n      color=\"yellow\"\n    />\n    <styled.span\n      data-id=\"diagnostic-message\"\n    >\n      an error here\n    </styled.span>\n  </styled.div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/ExternalMenus.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<ExternalMenus /> Should match the last snapshot 1`] = `\n<styled.div\n  loaded={false}\n  visible={true}\n/>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/NodeView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<NodeView /> Should match the snapshot 1`] = `\n<styled.div>\n  <div>\n    <DropTarget(DragSource(DragAndDrop))\n      accepts={\n        Array [\n          \"FILE\",\n          \"FOLDER\",\n        ]\n      }\n      dragTarget=\"FILE\"\n      isValidDrop={[Function]}\n      node={\n        Object {\n          \"filePath\": \"/test/a/file.txt\",\n          \"id\": \"2\",\n          \"indentationLevel\": 2,\n          \"modified\": false,\n          \"name\": \"file.txt\",\n          \"type\": \"file\",\n        }\n      }\n      onDrop={[Function]}\n      render={[Function]}\n    />\n  </div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/NotificationView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<NotificationsView /> should match the snapshot 1`] = `\n<styled.div\n  className=\"notification\"\n  data-test=\"notification\"\n  key=\"1\"\n  level=\"info\"\n  onClick={[Function]}\n>\n  <styled.header>\n    <styled.div>\n      <styled.div\n        level=\"info\"\n      >\n        <Sneakable\n          callback={[Function]}\n        >\n          <Icon\n            name=\"info-circle\"\n            size={1}\n          />\n        </Sneakable>\n      </styled.div>\n      <styled.div\n        onClick={[Function]}\n      >\n        <Sneakable\n          callback={[Function]}\n        >\n          <Icon\n            name=\"times\"\n            size={1}\n          />\n        </Sneakable>\n      </styled.div>\n    </styled.div>\n    <styled.div\n      data-test=\"notification-title\"\n      level=\"info\"\n    >\n      testing1\n    </styled.div>\n  </styled.header>\n  <styled.div>\n    <styled.div\n      className=\"notification-description\"\n    >\n      this is a test\n    </styled.div>\n  </styled.div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/QuickInfo.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<QuickInfo /> renders a shallow instance of the component 1`] = `\"\"`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/Tabs.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<Tabs /> Tests should match last known snapshot unless we make a change 1`] = `\n<styled.div\n  data-id=\"tabs\"\n  fontFamily=\"inherit\"\n  fontSize=\"1.2em\"\n  shouldWrap={false}\n>\n  <Tab\n    description=\"a test tab\"\n    height=\"2em\"\n    highlightColor=\"#000\"\n    iconFileName=\"icon\"\n    id={1}\n    isDirty={true}\n    isSelected={true}\n    key=\"1\"\n    maxWidth=\"20em\"\n    mode=\"normal\"\n    name=\"test\"\n    onClickClose={[Function]}\n    onClickName={[Function]}\n    shouldShowHighlight={true}\n  />\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/Text.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<Text/SelectedText /> SelectedText component should match the last snapshot on record 1`] = `\n<styled.span>\n  Test\n</styled.span>\n`;\n\nexports[`<Text/SelectedText /> Text component should match the last snapshot on record 1`] = `\n<span>\n  Test\n</span>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/WelcomeCommandsView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Welcome Layer test should match last snapshot on record 1`] = `\n<styled.div>\n  <styled.div\n    duration=\"0.25s\"\n  >\n    <styled.div>\n      Quick Commands\n    </styled.div>\n    <WelcomeButton\n      command=\"button1\"\n      description=\"Control + N\"\n      onClick={[Function]}\n      selected={true}\n      title=\"New File\"\n    />\n    <WelcomeButton\n      command=\"button6\"\n      description=\"Control + O\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Open File / Folder\"\n    />\n    <WelcomeButton\n      command=\"button7\"\n      description=\"Control + Shift + P\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Command Palette\"\n    />\n    <WelcomeButton\n      command=\"editor.openExCommands\"\n      description=\":\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Vim Ex Commands\"\n    />\n  </styled.div>\n  <styled.div\n    duration=\"0.25s\"\n  >\n    <styled.div>\n      Learn\n    </styled.div>\n    <WelcomeButton\n      command=\"button2\"\n      description=\"Learn modal editing with an interactive tutorial.\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Tutor\"\n    />\n    <WelcomeButton\n      command=\"button3\"\n      description=\"Discover what Oni can do for you.\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Documentation\"\n    />\n  </styled.div>\n  <styled.div\n    duration=\"0.25s\"\n  >\n    <styled.div>\n      Customize\n    </styled.div>\n    <WelcomeButton\n      command=\"button4\"\n      description=\"Make Oni work the way you want.\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Configure\"\n    />\n    <WelcomeButton\n      command=\"button5\"\n      description=\"Choose a theme that works for you.\"\n      onClick={[Function]}\n      selected={false}\n      title=\"Themes\"\n    />\n  </styled.div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/WelcomeView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<WelcomeView /> should match its last snapshot 1`] = `\n<styled.div\n  data-id=\"welcome-screen\"\n  height=\"100%\"\n  innerRef={\n    Object {\n      \"current\": null,\n    }\n  }\n>\n  <styled.div\n    extension={\n      Array [\n        \"\n    width: 100%;\n    padding-top: 32px;\n    animation: \",\n        \"ckrRMN\",\n        \" 0.25s ease-in 0.25s forwards};\n\",\n      ]\n    }\n  >\n    <styled.div />\n    <styled.div\n      alignment=\"flex-end\"\n    >\n      <styled.div>\n        Oni\n      </styled.div>\n      <styled.div>\n        Modern Modal Editing\n      </styled.div>\n    </styled.div>\n    <styled.div\n      flex=\"0 0\"\n    >\n      <styled.img\n        src=\"images/oni-icon-no-border.svg\"\n      />\n    </styled.div>\n    <styled.div\n      alignment=\"flex-start\"\n    >\n      <div>\n        https://onivim.io\n      </div>\n    </styled.div>\n    <styled.div />\n  </styled.div>\n  <styled.div\n    extension={\n      Array [\n        \"\n    width: 60%;\n    height: 60%;\n    padding: 0 1em;\n    opacity: 1;\n    margin-top: 64px;\n    box-sizing: border-box;\n    border: 1px solid \",\n        [Function],\n        \";\n    border-radius: 4px;\n    overflow: hidden;\n    justify-content: space-around;\n    background-color: \",\n        [Function],\n        \";\n    \",\n        \"\n    box-shadow: inset 0 4px 8px 2px rgba(0, 0, 0, 0.2);\n\",\n        \";\n\",\n      ]\n    }\n  >\n    <Component\n      commands={\n        Object {\n          \"commandline\": Object {\n            \"command\": \"button8\",\n            \"execute\": [MockFunction],\n          },\n          \"openConfig\": Object {\n            \"command\": \"button4\",\n            \"execute\": [MockFunction],\n          },\n          \"openDocs\": Object {\n            \"command\": \"button3\",\n            \"execute\": [MockFunction],\n          },\n          \"openFile\": Object {\n            \"command\": \"button1\",\n            \"execute\": [MockFunction],\n          },\n          \"openThemes\": Object {\n            \"command\": \"button5\",\n            \"execute\": [MockFunction],\n          },\n          \"openTutor\": Object {\n            \"command\": \"button2\",\n            \"execute\": [MockFunction],\n          },\n          \"openWorkspaceFolder\": Object {\n            \"command\": \"button6\",\n            \"execute\": [MockFunction],\n          },\n          \"quickOpenShow\": Object {\n            \"command\": \"button7\",\n            \"execute\": [MockFunction],\n          },\n          \"restoreSession\": [MockFunction],\n        }\n      }\n      executeCommand={[MockFunction]}\n      selectedId=\"button1\"\n    />\n    <styled.div>\n      <styled.ul>\n        <styled.div>\n          Sessions\n        </styled.div>\n        <styled.li\n          isSelected={false}\n          key=\"test-1\"\n          onClick={[Function]}\n        >\n          <Icon\n            name=\"file\"\n            style={\n              Object {\n                \"marginRight\": \"0.3em\",\n              }\n            }\n          />\n           \n          test\n        </styled.li>\n      </styled.ul>\n    </styled.div>\n  </styled.div>\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/__snapshots__/WindowTitleView.test.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`<WindowTitleView /> Text component should match the last snapshot on record 1`] = `\n<styled.div\n  id=\"oni-titlebar\"\n  onDoubleClick={[Function]}\n>\n  Test Window\n</styled.div>\n`;\n"
  },
  {
    "path": "ui-tests/enzyme-adapter-react-16.d.ts",
    "content": "declare module \"enzyme-adapter-react-16\"\n"
  },
  {
    "path": "ui-tests/jestsetup.ts",
    "content": "// tslint:disable\nimport { configure } from \"enzyme\"\nimport * as Adapter from \"enzyme-adapter-react-16\"\n\n// React 16 Enzyme adapter\nconfigure({ adapter: new Adapter() })\n\n// Make Enzyme functions available in all test files without importing\n// ;(global as any).shallow = shallow\n// ;(global as any).render = render\n// ;(global as any).mount = mount\n"
  },
  {
    "path": "ui-tests/mocks/CommandManager.ts",
    "content": "import { CommandManager } from \"./../../browser/src/Services/CommandManager\"\n\nexport const mockRegisterCommands = jest.fn()\nconst MockCommands = jest.fn<CommandManager>().mockImplementation(() => ({\n    registerCommand: mockRegisterCommands,\n}))\n\nexport default MockCommands\n"
  },
  {
    "path": "ui-tests/mocks/Configuration.ts",
    "content": "import * as Oni from \"oni-api\"\n\nconst Configuration = jest.fn<Oni.Configuration>().mockImplementation(() => ({\n    onConfigurationChanged() {\n        return {\n            subscribe: jest.fn(),\n        }\n    },\n    notifyListeners: jest.fn(),\n    updateConfig: jest.fn(),\n    getValue: jest.fn(),\n}))\n\nexport const configuration = new Configuration()\n\nexport default Configuration\n"
  },
  {
    "path": "ui-tests/mocks/EditorManager.ts",
    "content": "import { Event } from \"oni-types\"\nimport { EditorManager } from \"./../../browser/src/Services/EditorManager\"\n\nconst _onBufferSaved = new Event<any>(\"Test:ActiveEditor-BufferSaved\")\nconst _onBufferEnter = new Event<any>(\"Test:ActiveEditor-BufferEnter\")\nconst _onQuit = new Event<void>()\n\nconst MockEditorManager = jest.fn<EditorManager>().mockImplementation(() => ({\n    activeEditor: {\n        onQuit: _onQuit,\n        activeBuffer: {\n            filePath: \"test.txt\",\n        },\n        onBufferEnter: _onBufferEnter,\n        onBufferSaved: _onBufferSaved,\n        restoreSession: jest.fn(),\n        persistSession: jest.fn(),\n        getCurrentSession: jest.fn().mockReturnValue(\"test-session\"),\n    },\n}))\n\nexport default MockEditorManager\n"
  },
  {
    "path": "ui-tests/mocks/MenuManager.ts",
    "content": "import { MenuManager } from \"./../../browser/src/Services/Menu\"\n\nexport const mockMenuShow = jest.fn()\nconst MockMenu = jest.fn<MenuManager>().mockImplementation(() => ({\n    create() {\n        return {\n            show: mockMenuShow,\n            setItems(items: {}) {\n                return items\n            },\n            onItemSelected: {\n                subscribe: jest.fn(),\n            },\n        }\n    },\n}))\n\nexport default MockMenu\n"
  },
  {
    "path": "ui-tests/mocks/Notifications.ts",
    "content": "import { Notifications } from \"./../../browser/src/Services/Notifications\"\n\nconst MockNotifications = jest.fn<Notifications>().mockImplementation(() => ({}))\nexport default MockNotifications\n"
  },
  {
    "path": "ui-tests/mocks/Oni.ts",
    "content": "import * as Oni from \"oni-api\"\n\nimport MockCommands from \"./CommandManager\"\nimport MockEditorManager from \"./EditorManager\"\nimport MockMenu from \"./MenuManager\"\nimport MockSidebar from \"./../mocks/Sidebar\"\nimport MockStatusbar from \"./Statusbar\"\nimport MockWorkspace from \"./Workspace\"\n\nconst MockOni = jest\n    .fn<Oni.Plugin.Api>()\n    .mockImplementation((values: { apiMock: { [k: string]: any } }) => {\n        const commands = new MockCommands()\n        const editors = new MockEditorManager()\n        const sidebar = new MockSidebar()\n        const statusBar = new MockStatusbar()\n        const workspace = new MockWorkspace()\n\n        return {\n            commands,\n            configuration: {\n                getValue: jest.fn(),\n            },\n            editors,\n            sidebar,\n            statusBar,\n            workspace,\n            filter: null,\n            input: null,\n            language: null,\n            log: null,\n            notifications: null,\n            overlays: null,\n            plugins: null,\n            search: null,\n            ui: null,\n            menu: null,\n            process: null,\n            recorder: null,\n            snippets: null,\n            windows: null,\n            automation: null,\n            colors: null,\n            contextMenu: null,\n            diagnostics: null,\n            populateQuickFix(entries: Oni.QuickFixEntry[]): void {\n                throw Error(\"Not yet implemented\")\n            },\n            ...values,\n        }\n    })\n\nexport default MockOni\n"
  },
  {
    "path": "ui-tests/mocks/PersistentSettings.ts",
    "content": "export const get = jest.fn()\n\nexport const PersistedConfiguration = jest.fn().mockImplementation(() => {\n    return {\n        getPersistedValues: jest.fn(),\n        setPersistedValues: jest.fn(),\n    }\n})\n"
  },
  {
    "path": "ui-tests/mocks/SharedNeovimInstance.ts",
    "content": "const SharedNeovimInstance = jest.fn().mockImplementation(() => ({\n    bindToMenu: () => ({\n        setItems: jest.fn(),\n        onCursorMoved: {\n            subscribe: jest.fn(),\n        },\n    }),\n}))\n\nexport const getInstance = new SharedNeovimInstance()\n"
  },
  {
    "path": "ui-tests/mocks/Sidebar.ts",
    "content": "import { SidebarManager } from \"./../../browser/src/Services/Sidebar\"\n\nconst MockSidebar = jest.fn<SidebarManager>().mockImplementation(() => ({\n    add: jest.fn(),\n    entries: [\n        {\n            id: \"git-vcs\",\n        },\n    ],\n}))\n\nexport default MockSidebar\n"
  },
  {
    "path": "ui-tests/mocks/Statusbar.ts",
    "content": "import * as Oni from \"oni-api\"\n\nexport const mockStatusBarShow = jest.fn()\nexport const mockStatusBarHide = jest.fn()\nexport const mockStatusBarSetContents = jest.fn()\nexport const mockStatusBarDisposal = jest.fn()\n\nconst MockStatusbar = jest.fn<Oni.StatusBar>().mockImplementation(() => ({\n    createItem(alignment: number, vcsId: string) {\n        return {\n            show: mockStatusBarShow,\n            hide: mockStatusBarHide,\n            setContents: mockStatusBarSetContents,\n            dispose: mockStatusBarDisposal,\n        }\n    },\n}))\n\nexport default MockStatusbar\n"
  },
  {
    "path": "ui-tests/mocks/UserConfiguration.ts",
    "content": "export const getUserConfigFolderPath = jest.fn().mockReturnValue(\"~/.config/oni\")\n"
  },
  {
    "path": "ui-tests/mocks/Utility.ts",
    "content": "export const diff = jest.fn()\nexport const createCompletablePromise = jest.fn()\nexport const formatDate = jest.fn()\nexport const getTimeSince = jest.fn().mockReturnValue(\"2 days\")\n"
  },
  {
    "path": "ui-tests/mocks/Workspace.ts",
    "content": "import { Workspace } from \"./../../browser/src/Services/Workspace\"\n\nconst MockWorkspace = jest.fn<Workspace>().mockImplementation(() => ({\n    activeDirectory: \"test/dir\",\n    onDirectoryChanged: {\n        subscribe: jest.fn(),\n    },\n    onFocusGained: {\n        subscribe: jest.fn(),\n    },\n}))\n\nexport default MockWorkspace\n"
  },
  {
    "path": "ui-tests/mocks/electronMock.ts",
    "content": "export const remote = {\n    dialog: {\n        // replace the showOpenDialog function with a spy which returns a value\n        showOpenDialog: jest.fn().mockReturnValue(\"path/to/output folder\"),\n    },\n    require: (pkg: string) => jest.genMockFromModule(pkg),\n}\n"
  },
  {
    "path": "ui-tests/mocks/keyboardLayout.ts",
    "content": "const getCurrentKeyboardLanguage = jest.fn()\n\nexport const KeyboardLayoutManager = jest.fn().mockImplementation(() => {\n    return {\n        onKeyMapChanged: {\n            subscribe: jest.fn(),\n            dispatch: jest.fn(),\n        },\n        getCurrentKeyMap: jest.fn(),\n        getCurrentKeyboardLanguage,\n    }\n})\n\nexport default KeyboardLayoutManager\n"
  },
  {
    "path": "ui-tests/tsconfig.react.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowUnreachableCode\": false,\n        \"allowUnusedLabels\": false,\n        \"experimentalDecorators\": true,\n        \"allowSyntheticDefaultImports\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\", \"ES2015\"],\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"noEmitOnError\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"noImplicitAny\": true,\n        \"noImplicitReturns\": true,\n        \"noImplicitThis\": true,\n        \"noUnusedLocals\": true,\n        \"skipLibCheck\": true,\n        \"strictNullChecks\": false,\n        \"suppressImplicitAnyIndexErrors\": true,\n        \"target\": \"es2015\",\n        \"sourceMap\": true,\n        \"inlineSourceMap\": true,\n        \"types\": [\"jest\", \"electron\", \"react\", \"webgl2\"]\n    },\n    \"include\": [\"**/*.tsx\", \"**/*.ts\", \"../browser/**/*.ts\", \"../browser/**/*.tsx\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "ui-tests/welcomeLayer.test.tsx",
    "content": "import * as React from \"react\"\nimport { Event } from \"oni-types\"\n\nimport {\n    IWelcomeInputEvent,\n    OniWithActiveSection,\n    WelcomeBufferLayer,\n} from \"./../browser/src/Editor/NeovimEditor/WelcomeBufferLayer\"\nimport MockOni from \"./mocks/Oni\"\n\ndescribe(\"Welcome Layer tests\", () => {\n    const context = {\n        isActive: true,\n        windowId: 1,\n        fontPixelWidth: 3,\n        fontPixelHeight: 10,\n        cursorColumn: 4,\n        cursorLine: 30,\n        bufferToScreen: jest.fn(),\n        screenToPixel: jest.fn(),\n        bufferToPixel: jest.fn().mockReturnValue({\n            pixelX: 20,\n            pixelY: 20,\n        }),\n        dimensions: {\n            width: 100,\n            height: 100,\n            x: 0,\n            y: 0,\n        },\n        visibleLines: [],\n        topBufferLine: 20,\n        bottomBufferLine: 40,\n    }\n\n    const mockEvent = {\n        dispatch: jest.fn(),\n        subscribe: jest.fn(),\n    }\n\n    const mockRestoreSession = jest.fn()\n    const getActiveSectionMock = jest.fn()\n\n    let layer: WelcomeBufferLayer\n\n    const setup = () => {\n        const oni = new MockOni({\n            getActiveSection: jest.fn(),\n            sessions: { restoreSession: mockRestoreSession, allSessions: [] },\n        })\n        getActiveSectionMock.mockReturnValue(\"editor\")\n        layer = new WelcomeBufferLayer(oni as OniWithActiveSection)\n        layer.inputEvent = mockEvent as any\n    }\n\n    beforeEach(() => {\n        setup()\n    })\n\n    afterEach(() => {\n        mockEvent.dispatch.mockClear()\n        mockEvent.subscribe.mockClear()\n    })\n\n    it(\"should correctly return a component\", () => {\n        // this test can return the actual jsx but its difficult to test the exact return value\n        expect(layer.render(context)).toBeTruthy()\n    })\n\n    it(\"should correctly dispatch a right navigation event\", () => {\n        layer.handleInput(\"l\")\n        expect(mockEvent.dispatch.mock.calls[0][0]).toEqual({\n            horizontal: 1,\n            vertical: 0,\n            select: false,\n        })\n    })\n\n    it(\"should correctly dispatch a upwards navigation event\", () => {\n        layer.handleInput(\"k\")\n        expect(mockEvent.dispatch.mock.calls[0][0]).toEqual({\n            vertical: -1,\n            select: false,\n        })\n    })\n\n    it(\"should correctly dispatch a upwards navigation event\", () => {\n        layer.handleInput(\"j\")\n        expect(mockEvent.dispatch.mock.calls[0][0]).toEqual({\n            vertical: 1,\n            select: false,\n        })\n    })\n\n    it(\"should correctly return an active status of false if the editor is not active\", () => {\n        getActiveSectionMock.mockReturnValueOnce(\"commandline\")\n        expect(layer.isActive()).toBe(false)\n    })\n\n    it(\"should have the correct command names [THIS IS TO PREVENT WELCOME COMMAND REGRESSIONS]\", () => {\n        const existingCommands = [\n            \"oni.editor.newFile\",\n            \"workspace.openFolder\",\n            \"commands.show\",\n            \"editor.executeVimCommand\",\n            \"oni.tutor.open\",\n            \"oni.docs.open\",\n            \"oni.config.openUserConfig\",\n            \"oni.themes.open\",\n        ]\n        const props = layer.getProps()\n        expect(props.ids).toEqual(existingCommands)\n        expect(props.sections).toEqual([8])\n    })\n})\n"
  },
  {
    "path": "vim/core/colors/Monokai.vim",
    "content": "\" Vim color file\n\" Converted from Textmate theme Monokai using Coloration v0.3.2 (http://github.com/sickill/coloration)\n\nset background=dark\nhighlight clear\n\nif exists(\"syntax_on\")\n  syntax reset\nendif\n\nlet g:colors_name = \"Monokai\"\n\nhi Cursor ctermfg=235 ctermbg=231 cterm=NONE guifg=#272822 guibg=#f8f8f0 gui=NONE\nhi Visual ctermfg=NONE ctermbg=59 cterm=NONE guifg=NONE guibg=#49483e gui=NONE\nhi CursorLine ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE\nhi CursorColumn ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE\nhi ColorColumn ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE\nhi LineNr ctermfg=102 ctermbg=237 cterm=NONE guifg=#90908a guibg=#3c3d37 gui=NONE\nhi VertSplit ctermfg=241 ctermbg=241 cterm=NONE guifg=#64645e guibg=#64645e gui=NONE\nhi MatchParen ctermfg=197 ctermbg=NONE cterm=underline guifg=#f92672 guibg=NONE gui=underline\nhi StatusLine ctermfg=231 ctermbg=241 cterm=bold guifg=#f8f8f2 guibg=#64645e gui=bold\nhi StatusLineNC ctermfg=231 ctermbg=241 cterm=NONE guifg=#f8f8f2 guibg=#64645e gui=NONE\nhi Pmenu ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi PmenuSel ctermfg=NONE ctermbg=59 cterm=NONE guifg=NONE guibg=#49483e gui=NONE\nhi IncSearch ctermfg=235 ctermbg=186 cterm=NONE guifg=#272822 guibg=#e6db74 gui=NONE\nhi Search ctermfg=NONE ctermbg=NONE cterm=underline guifg=NONE guibg=NONE gui=underline\nhi Directory ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi Folded ctermfg=242 ctermbg=235 cterm=NONE guifg=#75715e guibg=#272822 gui=NONE\nhi SignColumn ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE\nhi Normal ctermfg=231 ctermbg=235 cterm=NONE guifg=#f8f8f2 guibg=#272822 gui=NONE\nhi Boolean ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi Character ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi Comment ctermfg=242 ctermbg=NONE cterm=NONE guifg=#75715e guibg=NONE gui=NONE\nhi Conditional ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi Constant ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi Define ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi DiffAdd ctermfg=231 ctermbg=64 cterm=bold guifg=#f8f8f2 guibg=#46830c gui=bold\nhi DiffDelete ctermfg=88 ctermbg=NONE cterm=NONE guifg=#8b0807 guibg=NONE gui=NONE\nhi DiffChange ctermfg=NONE ctermbg=NONE cterm=NONE guifg=#f8f8f2 guibg=#243955 gui=NONE\nhi DiffText ctermfg=231 ctermbg=24 cterm=bold guifg=#f8f8f2 guibg=#204a87 gui=bold\nhi ErrorMsg ctermfg=231 ctermbg=197 cterm=NONE guifg=#f8f8f0 guibg=#f92672 gui=NONE\nhi WarningMsg ctermfg=231 ctermbg=197 cterm=NONE guifg=#f8f8f0 guibg=#f92672 gui=NONE\nhi Float ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi Function ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE\nhi Identifier ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic\nhi Keyword ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi Label ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE\nhi NonText ctermfg=59 ctermbg=236 cterm=NONE guifg=#49483e guibg=#31322c gui=NONE\nhi Number ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi Operator ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi PreProc ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi Special ctermfg=231 ctermbg=NONE cterm=NONE guifg=#f8f8f2 guibg=NONE gui=NONE\nhi SpecialKey ctermfg=59 ctermbg=237 cterm=NONE guifg=#49483e guibg=#3c3d37 gui=NONE\nhi Statement ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi StorageClass ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic\nhi String ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE\nhi Tag ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi Title ctermfg=231 ctermbg=NONE cterm=bold guifg=#f8f8f2 guibg=NONE gui=bold\nhi Todo ctermfg=95 ctermbg=NONE cterm=inverse,bold guifg=#75715e guibg=NONE gui=inverse,bold\nhi Type ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi Underlined ctermfg=NONE ctermbg=NONE cterm=underline guifg=NONE guibg=NONE gui=underline\nhi rubyClass ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi rubyFunction ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE\nhi rubyInterpolationDelimiter ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi rubySymbol ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi rubyConstant ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic\nhi rubyStringDelimiter ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE\nhi rubyBlockParameter ctermfg=208 ctermbg=NONE cterm=NONE guifg=#fd971f guibg=NONE gui=italic\nhi rubyInstanceVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi rubyInclude ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi rubyGlobalVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi rubyRegexp ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE\nhi rubyRegexpDelimiter ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE\nhi rubyEscape ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi rubyControl ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi rubyClassVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi rubyOperator ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi rubyException ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi rubyPseudoVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi rubyRailsUserClass ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic\nhi rubyRailsARAssociationMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi rubyRailsARMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi rubyRailsRenderMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi rubyRailsMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi erubyDelimiter ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi erubyComment ctermfg=95 ctermbg=NONE cterm=NONE guifg=#75715e guibg=NONE gui=NONE\nhi erubyRailsMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi htmlTag ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi htmlEndTag ctermfg=NONE ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE\nhi htmlTagName ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi htmlArg ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi htmlSpecialChar ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi javaScriptFunction ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic\nhi javaScriptRailsFunction ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi javaScriptBraces ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi yamlKey ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE\nhi yamlAnchor ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi yamlAlias ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\nhi yamlDocumentHeader ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE\nhi cssURL ctermfg=208 ctermbg=NONE cterm=NONE guifg=#fd971f guibg=NONE gui=italic\nhi cssFunctionName ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi cssColor ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi cssPseudoClassId ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE\nhi cssClassName ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE\nhi cssValueLength ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE\nhi cssCommonAttr ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE\nhi cssBraces ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE\necho 'LOADED'\n"
  },
  {
    "path": "vim/core/oni-core-interop/plugin/init.vim",
    "content": "\" init.vim\n\" Entry point for oni-interop plugin\n\nif exists(\"g:loaded_oni_interop_plugin\")\n    finish\nendif\n\nset hidden\n\nlet g:loaded_oni_interop_plugin = 1\n\nfunction OniNotify(args)\n    call rpcnotify(1, \"oni_plugin_notify\", a:args)\nendfunction\n\nfunction OniNotifyWithBuffers(eventName)\n    \"NOTE: Get all buffers can return a 0 instead of a buffer\n    \" due to viml's implicit returns if a conditional fails\n    let l:allBufs = OniGetAllBuffers()\n    let l:current = OniGetContext()\n    let l:context = {}\n    let l:context.current = l:current\n    let l:context.existingBuffers = l:allBufs\n    call OniNotify([\"event\", a:eventName, l:context])\nendfunction\n\nfunction OniNoop()\n\nendfunction\n\nfunction OniNotifyBufferUpdate()\n\n    if !exists(\"b:last_change_tick\")\n        let b:last_change_tick = -1\n    endif\n\n    if b:changedtick > b:last_change_tick\n        let b:last_change_tick = b:changedtick\n        if mode() == 'i'\n            let buffer_line = line(\".\")\n            let line_contents = getline(\".\")\n            let context = OniGetContext()\n            call OniNotify([\"incremental_buffer_update\", context, line_contents, buffer_line])\n        else\n            let context = OniGetContext()\n            call OniNotify([\"buffer_update\", context, 1, line('$')])\n        endif\n    endif\nendfunction\n\nfunction OniNotifyEvent(eventName)\n    let context = OniGetContext()\n    call OniNotify([\"event\", a:eventName, context])\nendfunction\n\n\nfunction! s:filter_buffer(i)\n  return bufexists(a:i) && buflisted(a:i) && \"quickfix\" !=? getbufvar(a:i, \"&buftype\")\nendfunction\n\nfunction User_buffers() \" help buffers are always unlisted, but quickfix buffers are not\n  return filter(range(1,bufnr('$')),'s:filter_buffer(v:val)')\nendfunction\n\nfunction OniGetAllBuffers()\n  let l:buffers = []\n  let l:bufnums = User_buffers()\n  if exists(\"l:bufnums\")\n    for l:bufnum in l:bufnums\n      try\n        let l:buffer = OniGetEachContext(l:bufnum)\n        let l:buffers += [l:buffer]\n      catch /.*/\n      \"Probably dont want this outside of a debugging scenario\n      \" echohl WarningMsg\n      \" echo v:exception\n      \" echohl none\n    endtry\n    endfor\n    return l:buffers\n  endif\nendfunction\n\n\nfunction OniGetEachContext(bufnum)\n  let l:context = {}\n    let l:bufpath = bufname(a:bufnum)\n\n    if strlen(l:bufpath)\n      let l:context.bufferNumber = a:bufnum\n      let l:context.bufferFullPath = expand(\"#\".a:bufnum.\":p\")\n      let l:context.filetype = getbufvar(a:bufnum, \"&filetype\")\n      let l:context.buftype = getbufvar(a:bufnum, \"&buftype\")\n      let l:context.modified = getbufvar(a:bufnum, \"&mod\")\n      let l:context.hidden = getbufvar(a:bufnum, \"&hidden\")\n      let l:context.listed = getbufvar(a:bufnum, \"&buflisted\")\n\n      if exists(\"b:last_change_tick\")\n        let l:context.version = b:last_change_tick\n      endif\n\n      return l:context\n    elseif -1 < index(['nofile','acwrite'], getbufvar(a:bufnum, '&buftype')) \" scratch buffer\n        return\n  endif\nendif\nendfunction\n\nfunction OniCommand(oniCommand, ...)\n    let l:function_command_and_args = {}\n    let l:function_command_and_args.command = a:oniCommand\n    let l:function_command_and_args.args = a:000\n\n    call OniNotify([\"oni_command\", l:function_command_and_args])\nendfunction\n\naugroup OniClipboard\n    autocmd!\n    autocmd! TextYankPost * :call OniNotifyYank(v:event)\naugroup end\n\naugroup OniEventListeners\n    autocmd!\n    autocmd! BufWritePre * :call OniNotifyEvent(\"BufWritePre\")\n    autocmd! BufWritePost * :call OniNotifyEvent(\"BufWritePost\")\n    autocmd! BufEnter * :call OniNotifyWithBuffers(\"BufEnter\")\n    autocmd! BufRead * :call OniNotifyWithBuffers(\"BufRead\")\n    autocmd! BufWinEnter * :call OniNotifyWithBuffers(\"BufWinEnter\")\n    autocmd! ColorScheme * :call OniNotifyEvent(\"ColorScheme\")\n    autocmd! FileType * :call OniNotifyEvent(\"FileType\")\n    autocmd! WinEnter * :call OniNotifyEvent(\"WinEnter\")\n    autocmd! BufDelete * :call OniNotifyWithBuffers(\"BufDelete\")\n    autocmd! BufUnload * :call OniNotifyWithBuffers(\"BufUnload\")\n    autocmd! BufWipeout * :call OniNotifyWithBuffers(\"BufWipeout\")\n    autocmd! CursorMoved * :call OniNotifyEvent(\"CursorMoved\")\n    autocmd! CursorMovedI * :call OniNotifyEvent(\"CursorMovedI\")\n    autocmd! InsertLeave * :call OniNotifyEvent(\"InsertLeave\")\n    autocmd! InsertEnter * :call OniNotifyEvent(\"InsertEnter\")\n    autocmd! DirChanged * :call OniNotifyEvent(\"DirChanged\")\n    autocmd! VimResized * :call OniNotifyEvent(\"VimResized\")\n    autocmd! VimLeave * :call OniNotifyEvent(\"VimLeave\")\naugroup END\n\naugroup OniNotifyBufferUpdates\n    autocmd!\n    autocmd! BufEnter * :call OniNotifyBufferUpdate()\n    autocmd! CursorMovedI * :call OniNotifyBufferUpdate()\n    autocmd! CursorMoved * :call OniNotifyBufferUpdate()\n    autocmd! InsertLeave * :call OniNotifyBufferUpdate()\n    autocmd! InsertChange * :call OniNotifyBufferUpdate()\n    autocmd! InsertEnter * :call OniNotifyBufferUpdate()\naugroup END\n\nfunction OniGetContext()\nlet context = {}\nlet context.bufferNumber = bufnr(\"%\")\nlet context.bufferFullPath = expand(\"%:p\")\nlet context.bufferTotalLines = line(\"$\")\nlet context.line = line(\".\")\nlet context.column = col(\".\")\nlet context.mode = mode()\nlet context.tabNumber = tabpagenr()\nlet context.windowNumber = win_getid()\nlet context.winline = winline()\nlet context.wincol = wincol()\nlet context.windowTopLine = line(\"w0\")\nlet context.windowBottomLine = line(\"w$\")\nlet context.windowWidth = winwidth(winnr())\nlet context.windowHeight = winheight(winnr())\nlet context.byte = line2byte (line ( \".\" ) ) + col ( \".\" ) - 1\nlet context.filetype = eval(\"&filetype\")\nlet context.modified = &modified\nlet context.hidden = &hidden\nlet context.listed = &buflisted\nlet context.tabstop = &tabstop\nlet context.shiftwidth = shiftwidth()\nlet context.comments = &comments\n\nif exists(\"b:last_change_tick\")\n    let context.version = b:last_change_tick\nendif\n\nreturn context\nendfunction\n\nfunction OniNotifyYank(yankEvent)\n    call OniNotify([\"oni_yank\", a:yankEvent])\nendfunction\n\n\n\" Window navigation excerpt from:\n\" http://blog.paulrugelhiatt.com/vim/2014/10/31/vim-tip-automatically-create-window-splits-with-movement.html\n\nfunction! s:GotoNextWindow( direction )\n  let l:prevWinNr = winnr()\n  execute 'wincmd' a:direction\n  return winnr() != l:prevWinNr\nendfunction\n\nfunction! OniNextWindow( direction )\n  if ! s:GotoNextWindow(a:direction)\n    if a:direction == 'h'\n      call OniCommand(\"window.moveLeft\")\n    elseif a:direction == 'j'\n      call OniCommand(\"window.moveDown\")\n    elseif a:direction == 'k'\n      call OniCommand(\"window.moveUp\")\n    elseif a:direction == 'l'\n      call OniCommand(\"window.moveRight\")\n    endif\n    execute 'wincmd' a:direction\n  endif\nendfunction\n\nfunction! OniSetMarkAndReport(mark)\n     execute 'normal! m' . a:mark\n    call OniCommand(\"_internal.notifyMarksChanged\")\nendfunction\n\nlet s:all_marks = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\n\nfunction! OniListenForMarks()\n\n    let n = 0\n    let s:maxmarks = strlen(s:all_marks)\n    while n < s:maxmarks\n        let c = strpart(s:all_marks, n, 1)\n        execute \"nnoremap <silent> m\" . c . \" :<C-u> call OniSetMarkAndReport('\" . c . \"')<CR>\"\n        let n = n + 1\n    endwhile\n    call OniCommand(\"_internal.notifyMarksChanged\")\nendfunction\n\nnnoremap <silent> gd :<C-u>call OniCommand(\"language.gotoDefinition\")<CR>\nnnoremap <silent> <C-w>h :<C-u>call OniNextWindow('h')<CR>\nnnoremap <silent> <C-w>j :<C-u>call OniNextWindow('j')<CR>\nnnoremap <silent> <C-w>k :<C-u>call OniNextWindow('k')<CR>\nnnoremap <silent> <C-w>l :<C-u>call OniNextWindow('l')<CR>\nnnoremap <silent> <C-w><C-h> :<C-u>call OniNextWindow('h')<CR>\nnnoremap <silent> <C-w><C-j> :<C-u>call OniNextWindow('j')<CR>\nnnoremap <silent> <C-w><C-k> :<C-u>call OniNextWindow('k')<CR>\nnnoremap <silent> <C-w><C-l> :<C-u>call OniNextWindow('l')<CR>\n\nnnoremap <silent> <C-w><s> :<C-u>call OniCommand('editor.split.horizontal')<CR>)\nnnoremap <silent> <C-w><C-s> :<C-u>call OniCommand('editor.split.horizontal')<CR>)\nnnoremap <silent> <C-w><v> :<C-u>call OniCommand('editor.split.vertical')<CR>)\nnnoremap <silent> <C-w><C-v> :<C-u>call OniCommand('editor.split.vertical')<CR>)\n"
  },
  {
    "path": "vim/core/oni-core-interop/readme.md",
    "content": "# oni-interop\n\nInterop layer for Oni to pull events\n"
  },
  {
    "path": "vim/core/oni-core-statusbar/index.js",
    "content": "const path = require(\"path\")\n\nconst rgb = (r, g, b) => `rgb(${r}, ${g}, ${b})`\n\nconst activate = Oni => {\n    const React = Oni.dependencies.React\n    const items = Oni.configuration.getValue(\"statusbar.priority\", {})\n    const ids = Object.keys(items)\n\n    const mode = ids.find(id => id.includes(\"mode\"))\n    const linenumber = ids.find(id => id.includes(\"linenumber\"))\n    const dir = ids.find(id => id.includes(\"workingDir\"))\n    const gitHubRepo = ids.find(id => id.includes(\"gitHubRepo\"))\n\n    const workingDirectoryItem = Oni.statusBar.createItem(0, dir)\n    const lineNumberItem = Oni.statusBar.createItem(1, linenumber)\n    const modeItem = Oni.statusBar.createItem(1, mode)\n    const gitHubRepoItem = Oni.statusBar.createItem(1, gitHubRepo)\n\n    const setMode = mode => {\n        const getBackgroundColorForMode = m => {\n            switch (m) {\n                case \"insert\":\n                case \"replace\":\n                    return Oni.colors.getColor(\"highlight.mode.insert.background\")\n                case \"operator\":\n                    return Oni.colors.getColor(\"highlight.mode.operator.background\")\n                case \"visual\":\n                    return Oni.colors.getColor(\"highlight.mode.visual.background\")\n                default:\n                    return Oni.colors.getColor(\"highlight.mode.normal.background\")\n            }\n        }\n\n        const getForegroundColorForMode = m => {\n            switch (m) {\n                case \"insert\":\n                case \"replace\":\n                    return Oni.colors.getColor(\"highlight.mode.insert.foreground\")\n                case \"operator\":\n                    return Oni.colors.getColor(\"highlight.mode.operator.foreground\")\n                case \"visual\":\n                    return Oni.colors.getColor(\"highlight.mode.visual.foreground\")\n                default:\n                    return Oni.colors.getColor(\"highlight.mode.normal.foreground\")\n            }\n        }\n\n        const parseMode = m => {\n            // Need to change modes like `cmdline_insert`\n            if (m.indexOf(\"_\") >= 0) {\n                return m.split(\"_\")[1]\n            } else {\n                return m\n            }\n        }\n\n        const style = {\n            width: \"100%\",\n            height: \"100%\",\n            display: \"flex\",\n            alignItems: \"center\",\n            paddingLeft: \"8px\",\n            paddingRight: \"8px\",\n            textTransform: \"uppercase\",\n            color: getForegroundColorForMode(mode),\n            backgroundColor: getBackgroundColorForMode(mode),\n        }\n\n        const modeElement = React.createElement(\n            \"div\",\n            { style, className: \"mode\" },\n            parseMode(mode),\n        )\n        modeItem.setContents(modeElement)\n    }\n\n    const setLineNumber = (line, column) => {\n        const element = React.createElement(\"div\", null, `${line}, ${column}`)\n        lineNumberItem.setContents(element)\n    }\n\n    const setWorkingDirectory = workingDirectory => {\n        if (!workingDirectory) {\n            workingDirectory = \"\"\n        }\n\n        const openFolderCommand = () => {\n            Oni.commands.executeCommand(\"workspace.openFolder\")\n        }\n\n        const element = React.createElement(\n            \"div\",\n            {\n                style: {\n                    color: \"rgb(140, 140, 140)\",\n                    maxWidth: \"25rem\",\n                    textOverflow: \"ellipsis\",\n                    whitespace: \"nowrap\",\n                    overflow: \"hidden\",\n                },\n                onClick: openFolderCommand,\n            },\n            workingDirectory,\n        )\n        workingDirectoryItem.setContents(element)\n    }\n\n    const setGitHubRepo = () => {\n        const openGitHubRepoCommand = () => {\n            Oni.commands.executeCommand(\"browser.openUrl\", \"https://github.com/onivim/oni\")\n        }\n\n        const gitHubIcon = Oni.ui.createIcon({\n            name: \"github\",\n            size: Oni.ui.iconSize.Default,\n        })\n\n        const element = React.createElement(\"div\", { onClick: openGitHubRepoCommand }, gitHubIcon)\n        gitHubRepoItem.setContents(element)\n    }\n\n    Oni.editors.activeEditor.onModeChanged.subscribe(newMode => {\n        setMode(newMode)\n    })\n\n    Oni.editors.activeEditor.onCursorMoved.subscribe(cursor => {\n        setLineNumber(cursor.line + 1, cursor.column + 1)\n    })\n\n    Oni.workspace.onDirectoryChanged.subscribe(newDirectory => {\n        setWorkingDirectory(newDirectory)\n    })\n\n    setMode(\"normal\")\n    setLineNumber(1, 1)\n    setWorkingDirectory(null)\n    setWorkingDirectory(process.cwd())\n    setGitHubRepo()\n\n    modeItem.show()\n    lineNumberItem.show()\n    workingDirectoryItem.show()\n    gitHubRepoItem.show()\n}\n\nmodule.exports = {\n    activate,\n}\n"
  },
  {
    "path": "vim/core/oni-core-statusbar/package.json",
    "content": "{\n    \"name\": \"oni-plugin-statusbar\",\n    \"version\": \"0.0.1\",\n    \"main\": \"index.js\",\n    \"engines\": {\n        \"oni\": \"^0.2.3\"\n    },\n    \"scripts\": {},\n    \"oni\": {\n        \"supportedFileTypes\": [\"*\"]\n    },\n    \"dependencies\": {},\n    \"devDependencies\": {}\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-buffers/index.js",
    "content": "// @ts-check\nconst path = require(\"path\")\n\nconst OniApi = require(\"oni-api\")\n\nconst activate = Oni => {\n    const menu = Oni.menu.create()\n\n    const truncateFilePath = filepath => {\n        const sections = filepath.split(path.sep)\n        const folderAndFiles = sections.slice(-2)\n        return folderAndFiles.join(path.sep)\n    }\n\n    const updateBufferList = (Oni, menu) => {\n        const buffers = Oni.editors.activeEditor.getBuffers()\n        const active = Oni.editors.activeEditor.activeBuffer.filePath\n\n        const validBuffers = buffers.filter(b => !b.filepath)\n\n        const bufferMenuItems = validBuffers.map(b => ({\n            label: `${active === b.filePath ? b.id + \" %\" : b.id}`,\n            detail: truncateFilePath(b.filePath),\n            icon: Oni.ui.getIconClassForFile(b.filePath),\n            pinned: active === b.filePath,\n            metadata: { filePath: b.filePath, id: b.id },\n        }))\n\n        return bufferMenuItems\n    }\n\n    const createBufferList = () => {\n        const buffers = updateBufferList(Oni, menu)\n        menu.show()\n        menu.setItems(buffers)\n    }\n\n    const toggleBufferList = () => {\n        !menu.isOpen() ? createBufferList() : menu.hide()\n    }\n\n    const deleteBuffer = async menu => {\n        if (menu.selectedItem) {\n            const id = menu.selectedItem.label.includes(\"%\") ? \"%\" : menu.selectedItem.metadata.id\n            await Oni.editors.activeEditor.bufferDelete(id)\n            menu.hide()\n        }\n    }\n\n    const openBuffer = (menu, orientation) => {\n        orientation = orientation || OniApi.FileOpenMode.Edit\n        if (menu.selectedItem && menu.isOpen()) {\n            const buffers = Oni.editors.activeEditor.getBuffers()\n            try {\n                const { filePath = \"\" } = menu.selectedItem.metadata\n                Oni.editors.activeEditor.openFile(filePath, { openMode: orientation })\n            } catch (e) {\n                console.warn(\"[Oni Buffer Plugin Error]: \", e)\n            } finally {\n                menu.hide()\n            }\n        }\n        return\n    }\n\n    Oni.commands.registerCommand({\n        command: \"buffer.delete\",\n        name: \"Delete Selected Buffer\",\n        execute: async () => menu.isOpen() && (await deleteBuffer(menu)),\n    })\n\n    Oni.commands.registerCommand({\n        command: \"buffer.split\",\n        name: \"Split Selected Buffer\",\n        execute: () => menu.isOpen() && openBuffer(menu, OniApi.FileOpenMode.HorizontalSplit),\n    })\n\n    Oni.commands.registerCommand({\n        command: \"buffer.vsplit\",\n        name: \"Vertical Split Selected Buffer\",\n        execute: () => menu.isOpen() && openBuffer(menu, OniApi.FileOpenMode.VerticalSplit),\n    })\n\n    Oni.commands.registerCommand({\n        command: \"buffer.tabedit\",\n        name: \"Open Selected Buffer in a Tab\",\n        execute: () => menu.isOpen() && openBuffer(menu, OniApi.FileOpenMode.NewTab),\n    })\n\n    Oni.commands.registerCommand({\n        command: \"buffer.open\",\n        name: \"Open Bufferlist \",\n        detail: \"Open A List of All Available Buffers\",\n        execute: createBufferList,\n    })\n\n    Oni.commands.registerCommand({\n        command: \"buffer.toggle\",\n        name: \"Toggle Bufferlist \",\n        detail: \"Toggle A List of All Available Buffers\",\n        execute: toggleBufferList,\n    })\n\n    menu.onItemSelected.subscribe(menuItem => {\n        if (menuItem && menuItem.detail) {\n            openBuffer(menu, { openMode: OniApi.FileOpenMode.Edit })\n        }\n    })\n\n    Oni.editors.activeEditor.onBufferEnter.subscribe(() => updateBufferList(Oni, menu))\n}\n\nmodule.exports = { activate }\n"
  },
  {
    "path": "vim/core/oni-plugin-buffers/jsconfig.json",
    "content": "{\n    \"checkJs\": true\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-buffers/package.json",
    "content": "{\n    \"name\": \"oni-plugin-buffers\",\n    \"version\": \"1.0.0\",\n    \"main\": \"index.js\",\n    \"engines\": {\n        \"oni\": \"^0.2.6\"\n    },\n    \"scripts\": {},\n    \"oni\": {\n        \"supportedFileTypes\": [\"*\"]\n    },\n    \"dependencies\": {},\n    \"devDependencies\": {}\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-git/package.json",
    "content": "{\n    \"name\": \"oni-plugin-git\",\n    \"version\": \"1.0.0\",\n    \"main\": \"lib/index.js\",\n    \"engines\": {\n        \"oni\": \"^0.2.6\"\n    },\n    \"scripts\": {\n        \"build\": \"rimraf lib && tsc\",\n        \"test\": \"tsc -p tsconfig.test.json && mocha --recursive ./lib_test/test\"\n    },\n    \"oni\": {\n        \"supportedFileTypes\": [\n            \"*\"\n        ]\n    },\n    \"dependencies\": {\n        \"oni-api\": \"^0.0.46\",\n        \"oni-types\": \"^0.0.8\",\n        \"simple-git\": \"^1.96.0\"\n    },\n    \"devDependencies\": {\n        \"typescript\": \"^2.9.2\",\n        \"rimraf\": \"^2.6.2\"\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-git/src/index.tsx",
    "content": "/**\n * Git.ts\n *\n */\n\nimport * as Oni from \"oni-api\"\nimport { Event, IEvent } from \"oni-types\"\nimport * as GitP from \"simple-git/promise\"\n\nimport * as VCS from \"./vcs\" // TODO: import from oni-api\n\ninterface FileSummary {\n    index: string\n    path: string\n    working_dir: string\n}\n\nexport class GitVersionControlProvider implements VCS.VersionControlProvider {\n    private readonly _name = \"git\"\n    private _onPluginActivated = new Event<void>(\"Oni::VCSPluginActivated\")\n    private _onPluginDeactivated = new Event<void>(\"Oni::VCSPluginDeactivated\")\n    private _onBranchChange = new Event<VCS.BranchChangedEvent>(\"Oni::VCSBranchChanged\")\n    private _onStagedFilesChanged = new Event<VCS.StagedFilesChangedEvent>(\n        \"Oni::VCSStagedFilesChanged\",\n    )\n    private _onFileStatusChanged = new Event<VCS.FileStatusChangedEvent>(\n        \"Oni::VCSFilesStatusChanged\",\n    )\n    private _isActivated = false\n    private _projectRoot: string\n\n    constructor(private _oni: Oni.Plugin.Api, private _git = GitP) {\n        this._projectRoot = this._oni.workspace.activeWorkspace\n        this._oni.workspace.onDirectoryChanged.subscribe(workspace => {\n            this._projectRoot = workspace\n        })\n    }\n\n    get onBranchChanged(): IEvent<VCS.BranchChangedEvent> {\n        return this._onBranchChange\n    }\n\n    get onFileStatusChanged(): IEvent<VCS.FileStatusChangedEvent> {\n        return this._onFileStatusChanged\n    }\n\n    get onStagedFilesChanged(): IEvent<VCS.StagedFilesChangedEvent> {\n        return this._onStagedFilesChanged\n    }\n\n    get onPluginActivated(): IEvent<void> {\n        return this._onPluginActivated\n    }\n\n    get onPluginDeactivated(): IEvent<void> {\n        return this._onPluginDeactivated\n    }\n\n    get isActivated(): boolean {\n        return this._isActivated\n    }\n\n    get name(): VCS.SupportedProviders {\n        return this._name\n    }\n\n    public activate() {\n        this._isActivated = true\n        this._onPluginActivated.dispatch()\n    }\n\n    public deactivate() {\n        this._isActivated = false\n        this._onPluginDeactivated.dispatch()\n    }\n\n    public async canHandleWorkspace(dir?: string) {\n        try {\n            return this._git(this._projectRoot)\n                .silent()\n                .checkIsRepo()\n        } catch (e) {\n            this._oni.log.warn(\n                `Git provider was unable to check if this directory is a repository because ${\n                    e.message\n                }`,\n            )\n            return false\n        }\n    }\n\n    public async getRoot() {\n        try {\n            return this._git(this._projectRoot).revparse([\"--show-toplevel\"])\n        } catch (e) {\n            this._handleVCSError(e, `find vcs root`)\n        }\n    }\n\n    public getStatus = async (): Promise<VCS.StatusResult | void> => {\n        try {\n            const status = await this._git(this._projectRoot).status()\n            const { modified, staged } = this._getModifiedAndStaged(status.files)\n            return {\n                staged,\n                modified,\n                ahead: status.ahead,\n                behind: status.behind,\n                created: status.created,\n                deleted: status.deleted,\n                currentBranch: status.current,\n                conflicted: status.conflicted,\n                untracked: status.not_added,\n                remoteTrackingBranch: status.tracking,\n            }\n        } catch (e) {\n            this._handleVCSError(e, \"get current status\")\n        }\n    }\n\n    public getBlame = async (args: VCS.BlameArgs) => {\n        try {\n            const cmd = [\n                \"--no-pager\",\n                \"blame\",\n                \"--porcelain\",\n                args.file,\n                \"--show-number\",\n                \"-L\",\n                `${args.lineOne},${args.lineTwo}`,\n            ]\n            const raw = await this._git(this._projectRoot).raw(cmd)\n            return this._formatRawBlame(raw)\n        } catch (e) {\n            this._oni.log.warn(e)\n            return null\n        }\n    }\n\n    public unstage = async (files: string[]) => {\n        const flags = [\"HEAD\", ...files]\n        try {\n            await this._git(this._projectRoot).reset(flags)\n            const changed = files.map(path => ({ path, status: VCS.Statuses.modified }))\n            this._onFileStatusChanged.dispatch(changed)\n        } catch (e) {\n            this._handleVCSError(e, \"unstage the file\")\n        }\n    }\n\n    public uncommit = async (sha?: string) => {\n        try {\n            await this._git(this._projectRoot).reset([\"--soft\", \"HEAD^\"])\n            this._onFileStatusChanged.dispatch()\n        } catch (e) {\n            this._handleVCSError(e, \"undo most recent commit\")\n        }\n    }\n\n    public getLogs = async (file?: string): Promise<VCS.Logs> => {\n        try {\n            // n - represents the number of logs to get alternative is to use [\"--max-count=25\"]\n            const options = { file, n: 25 }\n            return this._git(this._projectRoot).log(options)\n        } catch (e) {\n            this._handleVCSError(e, \"get logs\")\n        }\n    }\n\n    public getDiff = async () => {\n        try {\n            return this._git(this._projectRoot).diffSummary()\n        } catch (e) {\n            this._handleVCSError(e, \"get current status\")\n        }\n    }\n\n    public commitFiles = async (message: string[], files?: string[]): Promise<VCS.Commits> => {\n        try {\n            const commit = await this._git(this._projectRoot).commit(message, files)\n            const changed = (files || []).map(file => ({\n                path: file,\n                status: VCS.Statuses.committed,\n            }))\n            this._onFileStatusChanged.dispatch(changed)\n            return commit\n        } catch (e) {\n            this._handleVCSError(e, \"commit files\")\n        }\n    }\n\n    public stageFile = async (file: string) => {\n        try {\n            await this._git(this._projectRoot).add(file)\n            this._onStagedFilesChanged.dispatch(file)\n            this._onFileStatusChanged.dispatch([{ path: file, status: VCS.Statuses.staged }])\n        } catch (e) {\n            this._handleVCSError(e, `add ${file}`)\n        }\n    }\n\n    public fetchBranchFromRemote = async ({\n        branch,\n        currentDir,\n        remote = null,\n    }: {\n        branch: string\n        remote: string\n        currentDir: string\n    }) => {\n        try {\n            return this._git(this._projectRoot).fetch(remote, branch)\n        } catch (e) {\n            this._handleVCSError(e, \"to fetch branch\")\n        }\n    }\n\n    public getLocalBranches = async () => {\n        try {\n            return this._git(this._projectRoot).branchLocal()\n        } catch (e) {\n            this._handleVCSError(e, \"get local branches\")\n        }\n    }\n\n    public getBranch = async (): Promise<string | void> => {\n        try {\n            const status = await this._git(this._projectRoot).status()\n            return status.current\n        } catch (e) {\n            this._handleVCSError(e, \"get current status\")\n        }\n    }\n\n    public async changeBranch(targetBranch: string) {\n        try {\n            await this._git(this._projectRoot).checkout(targetBranch)\n            this._onBranchChange.dispatch(targetBranch)\n        } catch (e) {\n            this._handleVCSError(e, \"change branch\")\n        }\n    }\n\n    private _handleVCSError(error: Error, attemptedAction: string) {\n        this._oni.log.warn(error)\n        throw new Error(\n            `[Oni Git Provider]: Unable to ${attemptedAction} because: ${error.message}`,\n        )\n    }\n\n    private _formatRawBlame(rawOutput: string): VCS.Blame {\n        if (!rawOutput) {\n            return null\n        }\n        const firstSpace = (str: string) => str.indexOf(\" \")\n        const blameArray = rawOutput.split(\"\\n\")\n        const formatted = blameArray\n            .map(line => [line.substr(0, firstSpace(line)), line.substr(firstSpace(line) + 1)])\n            .reduce<VCS.Blame>(\n                (acc, [key, value], index) => {\n                    const formattedKey = key.replace(\"-\", \"_\")\n                    if (!index && value) {\n                        acc.hash = formattedKey\n                        if (value) {\n                            const [originalLine, finalLine, numberOfLines] = value.split(\" \")\n                            acc.line = {\n                                originalLine,\n                                finalLine,\n                                numberOfLines,\n                            }\n                        }\n                        return acc\n                    } else if (!key) {\n                        return acc\n                    }\n                    acc[formattedKey] = value\n                    return acc\n                },\n                {} as VCS.Blame,\n            )\n        return formatted\n    }\n\n    private _isStaged = (file: FileSummary) => {\n        const GitPIndicators = [\"M\", \"A\"]\n        return GitPIndicators.some(status => file.index.includes(status))\n    }\n\n    private _getModifiedAndStaged(files: FileSummary[]): { modified: string[]; staged: string[] } {\n        return files.reduce(\n            (acc, file) => {\n                if (file.working_dir === \"M\") {\n                    acc.modified.push(file.path)\n                } else if (this._isStaged(file)) {\n                    acc.staged.push(file.path)\n                }\n                return acc\n            },\n            { modified: [], staged: [] },\n        )\n    }\n}\n\nexport const activate = async oni => {\n    const provider = new GitVersionControlProvider(oni)\n    await oni.services.vcs.registerProvider(provider)\n\n    return provider\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-git/src/vcs.ts",
    "content": "import { IEvent } from \"oni-types\"\nimport { BranchSummary, FetchResult } from \"simple-git/promise\"\n\nexport enum Statuses {\n    staged,\n    committed,\n    modified,\n}\n\nexport type BranchChangedEvent = string\nexport type StagedFilesChangedEvent = string\nexport type FileStatusChangedEvent = Array<{\n    path: string\n    status: Statuses\n}>\n\nexport interface StatusResult {\n    ahead: number\n    behind: number\n    currentBranch: string\n    modified: string[]\n    staged: string[]\n    conflicted: string[]\n    created: string[]\n    deleted: string[]\n    untracked: string[]\n    remoteTrackingBranch: string\n}\n\nexport interface BlameArgs {\n    lineOne: number\n    lineTwo: number\n    file: string\n}\n\nexport interface Blame {\n    author: string\n    author_mail: string\n    author_time: string\n    author_tz: string\n    committer: string\n    committer_mail: string\n    committer_time: string\n    committer_tz: string\n    filename: string\n    hash: string\n    line: { originalLine: string; finalLine: string; numberOfLines: string }\n    summary: string\n}\n\nexport interface VersionControlProvider {\n    // Events\n    onFileStatusChanged: IEvent<FileStatusChangedEvent>\n    onStagedFilesChanged: IEvent<StagedFilesChangedEvent>\n    onBranchChanged: IEvent<BranchChangedEvent>\n    onPluginActivated: IEvent<void>\n    onPluginDeactivated: IEvent<void>\n\n    name: SupportedProviders\n    isActivated: boolean\n    deactivate(): void\n    activate(): void\n    canHandleWorkspace(dir?: string): Promise<boolean>\n    getStatus(): Promise<StatusResult | void>\n    getRoot(): Promise<string | void>\n    getBlame(args: BlameArgs): Promise<Blame>\n    getDiff(): Promise<Diff | void>\n    getBranch(): Promise<string | void>\n    getLogs(file?: string): Promise<Logs>\n    getLocalBranches(): Promise<BranchSummary | void>\n    changeBranch(branch: string): Promise<void>\n    stageFile(file: string): Promise<void>\n    unstage(files: string[]): Promise<void>\n    uncommit(sha?: string): Promise<void>\n    commitFiles(message: string[], files?: string[]): Promise<Commits>\n    fetchBranchFromRemote(args: {\n        branch: string\n        origin?: string\n        currentDir: string\n    }): Promise<FetchResult>\n}\n\nexport interface DiffResultTextFile {\n    file: string\n    changes: number\n    insertions: number\n    deletions: number\n    binary: boolean\n}\n\nexport interface DiffResultBinaryFile {\n    file: string\n    before: number\n    after: number\n    binary: boolean\n}\n\nexport interface Diff {\n    files: Array<DiffResultTextFile | DiffResultBinaryFile>\n    insertions: number\n    deletions: number\n}\n\nexport interface Commits {\n    author: null | {\n        email: string\n        name: string\n    }\n    branch: string\n    commit: string\n    summary: {\n        changes: number\n        insertions: number\n        deletions: number\n    }\n}\n\nexport interface DefaultLogFields {\n    hash: string\n    date: string\n    message: string\n    author_name: string\n    author_email: string\n}\n\nexport interface ListLogSummary<T = DefaultLogFields> {\n    all: ReadonlyArray<T>\n    total: number\n    latest: T\n}\n\nexport type Logs = ListLogSummary<DefaultLogFields>\nexport type Summary = StatusResult\nexport type SupportedProviders = \"git\" | \"svn\"\nexport default VersionControlProvider\n"
  },
  {
    "path": "vim/core/oni-plugin-git/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"preserveConstEnums\": true,\n        \"outDir\": \"./lib\",\n        \"jsx\": \"react\",\n        \"lib\": [\"dom\", \"es2017\"],\n        \"declaration\": true,\n        \"sourceMap\": true,\n        \"target\": \"es2015\",\n        \"skipLibCheck\": true\n    },\n    \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-reasonml/ftdetect/reason.vim",
    "content": "au BufRead,BufNewFile *.re set filetype=reason\nau BufRead,BufNewFile *.rei set filetype=reason\n"
  },
  {
    "path": "vim/core/oni-plugin-reasonml/indent/reason.vim",
    "content": "\" Vim indent file\n\" Language:         Reason (adapted from Rust)\n\" Author:           Chris Morgan <me@chrismorgan.info> (Modifications by Jordan W)\n\" Portions Copyright (c) 2015-present, Facebook, Inc. All rights reserved\n\n\" Only load this indent file when no other was loaded.\nif exists(\"b:did_indent\")\n  finish\nendif\nlet b:did_indent = 1\n\n\" m1 is needed to make parens line up correct:\n\"\n\"   let result = callSomething (\n\"      1,\n\"      2\n\"   );\n\"\n\" fN (See the docs) - additional indentation *w.r.t the \"prevailing indent\" only applies to blocks\n\" *not* in nested braces!  We want it to match the blocks *inside* nested braces - and be zero, but\n\" the problem is that the \"prevailing indent\" not inside of braces is different than inside braces.\nsetlocal cinoptions=L0,(0,Ws,J1,j1,m1,{0,f0s\n\" cinkeys is ignored if indentexpr is activated so this setting is useless. See indentkeys below.\nsetlocal cinkeys=0{,0},0),!^F,o,O,0[,0]\n\" Don't think cinwords will actually do anything at all... never mind\nsetlocal cinwords=for,if,else,while,loop,impl,mod,unsafe,trait,struct,enum,fun,let,extern\n\n\" Some preliminary settings\nsetlocal nolisp\t\t\" Make sure lisp indenting doesn't supersede us\nsetlocal autoindent\t\" indentexpr isn't much help otherwise\n\" Also do indentkeys, otherwise # gets shoved to column 0 :-/\nsetlocal indentkeys=0{,0},0),!^F,o,O,0[,0]\n\n\nsetlocal indentexpr=GetReasonIndent(v:lnum)\n\n\" Only define the function once.\nif exists(\"*GetReasonIndent\")\n  finish\nendif\n\n\" Come here when loading the script the first time.\n\nfunction! s:get_line_trimmed(lnum)\n\t\" Get the line and remove a trailing comment.\n\t\" Use syntax highlighting attributes when possible.\n\t\" NOTE: this is not accurate; /* */ or a line continuation could trick it\n\tlet line = getline(a:lnum)\n\tlet line_len = strlen(line)\n\tif has('syntax_items')\n\t\t\" If the last character in the line is a comment, do a binary search for\n\t\t\" the start of the comment.  synID() is slow, a linear search would take\n\t\t\" too long on a long line.\n\t\tif synIDattr(synID(a:lnum, line_len, 1), \"name\") =~ 'Comment\\|Todo'\n\t\t\tlet min = 1\n\t\t\tlet max = line_len\n\t\t\twhile min < max\n\t\t\t\tlet col = (min + max) / 2\n\t\t\t\tif synIDattr(synID(a:lnum, col, 1), \"name\") =~ 'Comment\\|Todo'\n\t\t\t\t\tlet max = col\n\t\t\t\telse\n\t\t\t\t\tlet min = col + 1\n\t\t\t\tendif\n\t\t\tendwhile\n\t\t\tlet line = strpart(line, 0, min - 1)\n\t\tendif\n\t\treturn substitute(line, \"\\s*$\", \"\", \"\")\n\telse\n\t\t\" Sorry, this is not complete, nor fully correct (e.g. string \"//\").\n\t\t\" Such is life.\n\t\treturn substitute(line, \"\\s*//.*$\", \"\", \"\")\n\tendif\nendfunction\n\nfunction! s:is_string_comment(lnum, col)\n\tif has('syntax_items')\n\t\tfor id in synstack(a:lnum, a:col)\n\t\t\tlet synname = synIDattr(id, \"name\")\n\t\t\tif synname == \"rustString\" || synname =~ \"^rustComment\"\n\t\t\t\treturn 1\n\t\t\tendif\n\t\tendfor\n\telse\n\t\t\" without syntax, let's not even try\n\t\treturn 0\n\tendif\nendfunction\n\nfunction GetReasonIndent(lnum)\n\n\t\" Starting assumption: cindent (called at the end) will do it right\n\t\" normally. We just want to fix up a few cases.\n\n\tlet line = getline(a:lnum)\n\n\tif has('syntax_items')\n\t\tlet synname = synIDattr(synID(a:lnum, 1, 1), \"name\")\n\t\tif synname == \"rustString\"\n\t\t\t\" If the start of the line is in a string, don't change the indent\n\t\t\treturn -1\n\t\telseif synname =~ '\\(Comment\\|Todo\\)'\n\t\t\t\t\t\\ && line !~ '^\\s*/\\*'  \" not /* opening line\n\t\t\tif synname =~ \"CommentML\" \" multi-line\n\t\t\t\tif line !~ '^\\s*\\*' && getline(a:lnum - 1) =~ '^\\s*/\\*'\n\t\t\t\t\t\" This is (hopefully) the line after a /*, and it has no\n\t\t\t\t\t\" leader, so the correct indentation is that of the\n\t\t\t\t\t\" previous line.\n\t\t\t\t\treturn GetReasonIndent(a:lnum - 1)\n\t\t\t\tendif\n\t\t\tendif\n\t\t\t\" If it's in a comment, let cindent take care of it now. This is\n\t\t\t\" for cases like \"/*\" where the next line should start \" * \", not\n\t\t\t\" \"* \" as the code below would otherwise cause for module scope\n\t\t\t\" Fun fact: \"  /*\\n*\\n*/\" takes two calls to get right!\n\t\t\treturn cindent(a:lnum)\n\t\tendif\n\tendif\n\n\t\" cindent gets second and subsequent match patterns/struct members wrong,\n\t\" as it treats the comma as indicating an unfinished statement::\n\t\"\n\t\" switch a {\n\t\"   | b => c\n\t\"     | d => e\n\t\"     | f => g\n\t\" };\n\n\t\" Search backwards for the previous non-empty line.\n\tlet prevlinenum = prevnonblank(a:lnum - 1)\n\tlet prevline = s:get_line_trimmed(prevlinenum)\n\twhile prevlinenum > 1 && prevline !~ '[^[:blank:]]'\n\t\tlet prevlinenum = prevnonblank(prevlinenum - 1)\n\t\tlet prevline = s:get_line_trimmed(prevlinenum)\n\tendwhile\n\n\t\" Handle where clauses nicely: subsequent values should line up nicely.\n\tif prevline[len(prevline) - 1] == \",\"\n\t\t\t\t\\ && prevline =~# '^\\s*where\\s'\n\t\treturn indent(prevlinenum) + 6\n\tendif\n\n\tif prevline =~ \"\\s*|.*[{(\\[]$\"\n\t\t\t\t\" \\ && s:get_line_trimmed(a:lnum) !~ '^\\s*[\\[\\]{}]'\n\t\t\t\t\" \\ && prevline !~ '^\\s*fun\\s'\n\t\t\t\t\" \\ && prevline !~ '([^()]\\+,$'\n\t\t\" Oh ho! The previous line ended in a comma! I bet cindent will try to\n\t\t\" take this too far... For now, let's normally use the previous line's\n\t\t\" indent.\n\n\t\t\" One case where this doesn't work out is where *this* line contains\n\t\t\" square or curly brackets; then we normally *do* want to be indenting\n\t\t\" further.\n\t\t\"\n\t\t\" Another case where we don't want to is one like a function\n\t\t\" definition with arguments spread over multiple lines:\n\t\t\"\n\t\t\" fun foo(baz: Baz,\n\t\t\"        baz: Baz) // <-- cindent gets this right by itself\n\t\t\"\n\t\t\" Another case is similar to the previous, except calling a function\n\t\t\" instead of defining it, or any conditional expression that leaves\n\t\t\" an open paren:\n\t\t\"\n\t\t\" foo(baz,\n\t\t\"     baz);\n\t\t\"\n\t\t\" if baz && (foo ||\n\t\t\"            bar) {\n\t\t\"\n\t\t\" There are probably other cases where we don't want to do this as\n\t\t\" well. Add them as needed.\n\t\treturn indent(prevlinenum) + &shiftwidth\n\tendif\n\tif prevline =~ \"\\s*|\"\n\t\treturn indent(prevlinenum)\n\tendif\n\n\tif !has(\"patch-7.4.355\")\n\t\t\" cindent before 7.4.355 doesn't do the module scope well at all; e.g.::\n\t\t\"\n\t\t\" static FOO : &'static [bool] = [\n\t\t\" true,\n\t\t\"\t false,\n\t\t\"\t false,\n\t\t\"\t true,\n\t\t\"\t ];\n\t\t\"\n\t\t\"\t uh oh, next statement is indented further!\n\n\t\t\" Note that this does *not* apply the line continuation pattern properly;\n\t\t\" that's too hard to do correctly for my liking at present, so I'll just\n\t\t\" start with these two main cases (square brackets and not returning to\n\t\t\" column zero)\n\n\t\tcall cursor(a:lnum, 1)\n\t\tif searchpair('{\\|(', '', '}\\|)', 'nbW',\n\t\t\t\t\t\\ 's:is_string_comment(line(\".\"), col(\".\"))') == 0\n\t\t\tif searchpair('\\[', '', '\\]', 'nbW',\n\t\t\t\t\t\t\\ 's:is_string_comment(line(\".\"), col(\".\"))') == 0\n\t\t\t\t\" Global scope, should be zero\n\t\t\t\treturn 0\n\t\t\telse\n\t\t\t\t\" At the module scope, inside square brackets only\n\t\t\t\t\"if getline(a:lnum)[0] == ']' || search('\\[', '', '\\]', 'nW') == a:lnum\n\t\t\t\tif line =~ \"^\\\\s*]\"\n\t\t\t\t\t\" It's the closing line, dedent it\n\t\t\t\t\treturn 0\n\t\t\t\telse\n\t\t\t\t\treturn &shiftwidth\n\t\t\t\tendif\n\t\t\tendif\n\t\tendif\n\tendif\n\n\t\" Fall back on cindent, which does it mostly right\n\treturn cindent(a:lnum)\nendfunction\n"
  },
  {
    "path": "vim/core/oni-plugin-reasonml/syntax/reason.vim",
    "content": "\" Vim syntax file\n\" Language:     Reason (Forked from Rust)\n\" Maintainer:   (Jordan - for Reason changes) Patrick Walton <pcwalton@mozilla.com>\n\" Maintainer:   Ben Blum <bblum@cs.cmu.edu>\n\" Maintainer:   Chris Morgan <me@chrismorgan.info>\n\" Last Change:  January 29, 2015\n\" Portions Copyright (c) 2015-present, Facebook, Inc. All rights reserved.\n\nif version < 600\n  syntax clear\nelseif exists(\"b:current_syntax\")\n  finish\nendif\n\n\" Syntax definitions {{{1\n\" Basic keywords {{{2\nsyn keyword   rustConditional switch match if else for in\nsyn keyword   rustOperator    as\n\nsyn match     rustAssert      \"\\<assert\\(\\w\\)*!\" contained\nsyn match     rustPanic       \"\\<panic\\(\\w\\)*!\" contained\nsyn keyword   rustKeyword     box nextgroup=rustBoxPlacement skipwhite skipempty\nsyn keyword   rustKeyword     extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty\n\" syn keyword   rustKeyword     fun nextgroup=rustFuncName skipwhite skipempty\nsyn keyword   rustKeyword     unsafe where while\nsyn keyword   rustStorage     fun mutable class pub pri val inherit let rec nonrec and module type exception open include\n\" FIXME: Scoped impl's name is also fallen in this category\n\" syn keyword   rustStorageIdent   let and module type nextgroup=rustIdentifier skipwhite skipempty\n\nsyn keyword   rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty\n\" This is to get the `bar` part of `extern crate \"foo\" as bar;` highlighting.\nsyn match   rustExternCrateString /\".*\"\\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator\nsyn keyword   rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty\n\nsyn match     rustIdentifier  contains=rustIdentifierPrime \"\\%([^[:cntrl:][:space:][:punct:][:digit:]]\\|_\\)\\%([^[:cntrl:][:punct:][:space:]]\\|_\\)*\" display contained\nsyn match     rustFuncName    \"\\%([^[:cntrl:][:space:][:punct:][:digit:]]\\|_\\)\\%([^[:cntrl:][:punct:][:space:]]\\|_\\)*\" display contained\n\"\nsyn match labelArgument \"\\(\\l\\|_\\)\\(\\w\\|'\\)*::\\(?\\)\\?\"lc=0   \"Allows any space between label name and ::\nsyn match labelArgumentPunned \"::\\(?\\)\\?\\(\\l\\|_\\)\\(\\w\\|'\\)*\"lc=0   \"Allows any space between label name and ::\n\nsyn match    rustEnumVariant  \"\\<\\u\\(\\w\\|'\\)*\\>[^\\.]\"me=e-1\n\" Polymorphic variants\nsyn match    rustEnumVariant  \"`\\w\\(\\w\\|'\\)*\\>\"\n\nsyn match    rustModPath  \"\\<\\u\\w*\\.\"\n\n\nsyn region    rustBoxPlacement matchgroup=rustBoxPlacementParens start=\"(\" end=\")\" contains=TOP contained\n\" Ideally we'd have syntax rules set up to match arbitrary expressions. Since\n\" we don't, we'll just define temporary contained rules to handle balancing\n\" delimiters.\nsyn region    rustBoxPlacementBalance start=\"(\" end=\")\" containedin=rustBoxPlacement transparent\nsyn region    rustBoxPlacementBalance start=\"\\[\" end=\"\\]\" containedin=rustBoxPlacement transparent\n\" {} are handled by rustFoldBraces\n\n\nsyn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start=\"$(\" end=\")\" contains=TOP nextgroup=rustMacroRepeatCount\nsyn match rustMacroRepeatCount \".\\?[*+]\" contained\nsyn match rustMacroVariable \"$\\w\\+\"\n\n\" Reserved (but not yet used) keywords {{{2\nsyn keyword   rustReservedKeyword alignof become do offsetof priv pure sizeof typeof unsized yield abstract virtual final override macro\n\n\" Built-in types {{{2\nsyn keyword   rustType        int float option list array unit ref bool string\n\n\" Things from the libstd v1 prelude (src/libstd/prelude/v1.rs) {{{2\n\" This section is just straight transformation of the contents of the prelude,\n\" to make it easy to update.\n\n\" Reexported core operators {{{3\nsyn keyword   rustTrait       Copy Send Sized Sync\nsyn keyword   rustTrait       Drop Fn FnMut FnOnce\n\n\" Reexported functions {{{3\n\" There’s no point in highlighting these; when one writes drop( or drop::< it\n\" gets the same highlighting anyway, and if someone writes `let drop = …;` we\n\" don’t really want *that* drop to be highlighted.\n\"syn keyword rustFunction drop\n\n\" Reexported types and traits {{{3\nsyn keyword rustTrait Box\nsyn keyword rustTrait ToOwned\nsyn keyword rustTrait Clone\nsyn keyword rustTrait PartialEq PartialOrd Eq Ord\nsyn keyword rustTrait AsRef AsMut Into From\nsyn keyword rustTrait Default\nsyn keyword rustTrait Iterator Extend IntoIterator\nsyn keyword rustTrait DoubleEndedIterator ExactSizeIterator\nsyn keyword rustEnum Option\nsyn keyword rustEnumVariant Some None\nsyn keyword rustEnum Result\nsyn keyword rustEnumVariant Ok Err\nsyn keyword rustTrait SliceConcatExt\nsyn keyword rustTrait String ToString\nsyn keyword rustTrait Vec\n\n\" Other syntax {{{2\nsyn keyword   rustSelf        self\nsyn keyword   rustBoolean     true false\n\n\" This is merely a convention; note also the use of [A-Z], restricting it to\n\" latin identifiers rather than the full Unicode uppercase. I have not used\n\" [:upper:] as it depends upon 'noignorecase'\n\"syn match     rustCapsIdent    display \"[A-Z]\\w\\(\\w\\)*\"\n\nsyn match     rustOperator     display \"\\%(+\\|-\\|/\\|*\\|=\\|\\^\\|&\\||\\|!\\|>\\|<\\|%\\)=\\?\"\n\" This one isn't *quite* right, as we could have binary-& with a reference\n\n\" This isn't actually correct; a closure with no arguments can be `|| { }`.\n\" Last, because the & in && isn't a sigil\nsyn match     rustOperator     display \"&&\\|||\"\n\" This is rustArrowCharacter rather than rustArrow for the sake of matchparen,\n\" so it skips the ->; see http://stackoverflow.com/a/30309949 for details.\nsyn match     rustArrowCharacter display \"=>\"\n\nsyn match     rustEscapeError   display contained /\\\\./\nsyn match     rustEscape        display contained /\\\\\\([nrt0\\\\'\"]\\|x\\x\\{2}\\)/\nsyn match     rustEscapeUnicode display contained /\\\\\\(u\\x\\{4}\\|U\\x\\{8}\\)/\nsyn match     rustEscapeUnicode display contained /\\\\u{\\x\\{1,6}}/\nsyn match     rustStringContinuation display contained /\\\\\\n\\s*/\nsyn region    rustString      start=+b\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ contains=rustEscape,rustEscapeError,rustStringContinuation\nsyn region    rustString      start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell\nsyn region    rustString      start='b\\?r\\z(#*\\)\"' end='\"\\z1' contains=@Spell\n\nsyn region    rustAttribute   start=\"#!\\?\\[\" end=\"\\]\" contains=rustString,rustDerive\nsyn region    rustDerive      start=\"derive(\" end=\")\" contained contains=rustDeriveTrait\n\" This list comes from src/libsyntax/ext/deriving/mod.rs\n\" Some are deprecated (Encodable, Decodable) or to be removed after a new snapshot (Show).\nsyn keyword   rustDeriveTrait contained Clone Hash RustcEncodable RustcDecodable Encodable Decodable PartialEq Eq PartialOrd Ord Rand Show Debug Default FromPrimitive Send Sync Copy\n\n\" Number literals\nsyn match     rustDecNumber   display \"\\<[0-9][0-9_]*\\%([iu]\\%(size\\|8\\|16\\|32\\|64\\)\\)\\=\"\nsyn match     rustHexNumber   display \"\\<0x[a-fA-F0-9_]\\+\\%([iu]\\%(size\\|8\\|16\\|32\\|64\\)\\)\\=\"\nsyn match     rustOctNumber   display \"\\<0o[0-7_]\\+\\%([iu]\\%(size\\|8\\|16\\|32\\|64\\)\\)\\=\"\nsyn match     rustBinNumber   display \"\\<0b[01_]\\+\\%([iu]\\%(size\\|8\\|16\\|32\\|64\\)\\)\\=\"\n\n\" Special case for numbers of the form \"1.\" which are float literals, unless followed by\n\" an identifier, which makes them integer literals with a method call or field access,\n\" or by another \".\", which makes them integer literals followed by the \"..\" token.\n\" (This must go first so the others take precedence.)\nsyn match     rustFloat       display \"\\<[0-9][0-9_]*\\.\\%([^[:cntrl:][:space:][:punct:][:digit:]]\\|_\\|\\.\\)\\@!\"\n\" To mark a number as a normal float, it must have at least one of the three things integral values don't have:\n\" a decimal point and more numbers; an exponent; and a type suffix.\nsyn match     rustFloat       display \"\\<[0-9][0-9_]*\\%(\\.[0-9][0-9_]*\\)\\%([eE][+-]\\=[0-9_]\\+\\)\\=\\(f32\\|f64\\)\\=\"\nsyn match     rustFloat       display \"\\<[0-9][0-9_]*\\%(\\.[0-9][0-9_]*\\)\\=\\%([eE][+-]\\=[0-9_]\\+\\)\\(f32\\|f64\\)\\=\"\nsyn match     rustFloat       display \"\\<[0-9][0-9_]*\\%(\\.[0-9][0-9_]*\\)\\=\\%([eE][+-]\\=[0-9_]\\+\\)\\=\\(f32\\|f64\\)\"\n\n\" For the benefit of delimitMate\n\nsyn match   rustCharacterInvalid   display contained /b\\?'\\zs[\\n\\r\\t']\\ze'/\n\" The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII).\nsyn match   rustCharacterInvalidUnicode   display contained /b'\\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\\ze'/\nsyn match   rustCharacter   /b'\\([^\\\\]\\|\\\\\\(.\\|x\\x\\{2}\\)\\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode\nsyn match   rustCharacter   /'\\([^\\\\]\\|\\\\\\(.\\|x\\x\\{2}\\|u\\x\\{4}\\|U\\x\\{8}\\|u{\\x\\{1,6}}\\)\\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid\n\nsyn match rustShebang /\\%^#![^[].*/\nsyn region rustCommentLine                                        start=\"//\"                      end=\"$\"   contains=rustTodo,@Spell\nsyn region rustCommentLineDoc                                     start=\"//\\%(//\\@!\\|!\\)\"         end=\"$\"   contains=rustTodo,@Spell\nsyn region rustCommentBlock    matchgroup=rustCommentBlock        start=\"/\\*\\%(!\\|\\*[*/]\\@!\\)\\@!\" end=\"\\*/\" contains=rustTodo,rustCommentBlockNest,@Spell\nsyn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc     start=\"/\\*\\%(!\\|\\*[*/]\\@!\\)\"    end=\"\\*/\" contains=rustTodo,rustCommentBlockDocNest,@Spell\nsyn region rustCommentBlockNest matchgroup=rustCommentBlock       start=\"/\\*\"                     end=\"\\*/\" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent\nsyn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start=\"/\\*\"                     end=\"\\*/\" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent\n\" FIXME: this is a really ugly and not fully correct implementation. Most\n\" importantly, a case like ``/* */*`` should have the final ``*`` not being in\n\" a comment, but in practice at present it leaves comments open two levels\n\" deep. But as long as you stay away from that particular case, I *believe*\n\" the highlighting is correct. Due to the way Vim's syntax engine works\n\" (greedy for start matches, unlike Rust's tokeniser which is searching for\n\" the earliest-starting match, start or end), I believe this cannot be solved.\n\" Oh you who would fix it, don't bother with things like duplicating the Block\n\" rules and putting ``\\*\\@<!`` at the start of them; it makes it worse, as\n\" then you must deal with cases like ``/*/**/*/``. And don't try making it\n\" worse with ``\\%(/\\@<!\\*\\)\\@<!``, either...\n\nsyn keyword rustTodo contained TODO FIXME XXX NB NOTE\n\n\" Folding rules {{{2\n\" Trivial folding rules to begin with.\n\" FIXME: use the AST to make really good folding\nsyn region rustFoldBraces start=\"{\" end=\"}\" transparent fold\n\n\" Default highlighting {{{1\nhi def link labelArgument       Special\nhi def link labelArgumentPunned Special\nhi def link rustDecNumber       rustNumber\nhi def link rustHexNumber       rustNumber\nhi def link rustOctNumber       rustNumber\nhi def link rustBinNumber       rustNumber\nhi def link rustIdentifierPrime rustIdentifier\nhi def link rustTrait           rustType\nhi def link rustDeriveTrait     rustTrait\n\nhi def link rustMacroRepeatCount   rustMacroRepeatDelimiters\nhi def link rustMacroRepeatDelimiters   Macro\nhi def link rustMacroVariable Define\nhi def link rustEscape        Special\nhi def link rustEscapeUnicode rustEscape\nhi def link rustEscapeError   Error\nhi def link rustStringContinuation Special\nhi def link rustString        String\nhi def link rustCharacterInvalid Error\nhi def link rustCharacterInvalidUnicode rustCharacterInvalid\nhi def link rustCharacter     Character\nhi def link rustNumber        Number\nhi def link rustBoolean       Boolean\nhi def link rustEnum          rustType\nhi def link rustEnumVariant   Function\nhi def link rustModPath       Macro\nhi def link rustConstant      Constant\nhi def link rustSelf          Constant\nhi def link rustFloat         Float\nhi def link rustArrowCharacter rustOperator\nhi def link rustOperator      Keyword\nhi def link rustKeyword       Keyword\nhi def link rustReservedKeyword Error\nhi def link rustConditional   StorageClass\nhi def link rustIdentifier    Identifier\nhi def link rustCapsIdent     rustIdentifier\nhi def link rustFunction      Function\nhi def link rustFuncName      Function\nhi def link rustShebang       Comment\nhi def link rustCommentLine   Comment\nhi def link rustCommentLineDoc Comment\nhi def link rustCommentBlock  rustCommentLine\nhi def link rustCommentBlockDoc rustCommentLineDoc\nhi def link rustAssert        PreCondit\nhi def link rustPanic         PreCondit\nhi def link rustType          Type\nhi def link rustTodo          Todo\nhi def link rustAttribute     PreProc\nhi def link rustDerive        PreProc\nhi def link rustStorage       Conditional\nhi def link rustStorageIdent StorageClass\nhi def link rustObsoleteStorage Error\nhi def link rustExternCrate   rustKeyword\nhi def link rustObsoleteExternMod Error\nhi def link rustBoxPlacementParens Delimiter\n\n\" Other Suggestions:\n\" hi rustAttribute ctermfg=cyan\n\" hi rustDerive ctermfg=cyan\n\" hi rustAssert ctermfg=yellow\n\" hi rustPanic ctermfg=red\n\nsyn sync minlines=200\nsyn sync maxlines=500\n\nlet b:current_syntax = \"rust\"\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/.gitignore",
    "content": "lib_test/\nlib/\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/package.json",
    "content": "{\n    \"name\": \"oni-plugin-typescript\",\n    \"version\": \"0.0.1\",\n    \"main\": \"lib/index.js\",\n    \"engines\": {\n        \"oni\": \"^0.0.1\"\n    },\n    \"scripts\": {\n        \"build\": \"npm install && tsc\",\n        \"test\": \"npm install && tsc -p tsconfig.test.json && mocha --recursive ./lib_test/test\"\n    },\n    \"oni\": {\n        \"supportedFileTypes\": [\n            \"javascript\",\n            \"typescript\"\n        ]\n    },\n    \"dependencies\": {},\n    \"devDependencies\": {\n        \"@types/bluebird\": \"3.0.35\",\n        \"@types/es6-promise\": \"0.0.32\",\n        \"@types/lodash\": \"4.14.38\",\n        \"@types/mocha\": \"2.2.33\",\n        \"@types/node\": \"6.0.46\",\n        \"@types/sinon\": \"1.16.32\"\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/CodeActions.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { LanguageConnection } from \"./LightweightLanguageClient\"\nimport { IDocumentRangeFormattingParams } from \"./Types\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\nimport * as Utility from \"./Utility\"\n\ninterface ICodeActionRequestInfo {\n    filePath: string\n    range: types.Range\n}\n\nlet lastCodeActionRequestInfo: ICodeActionRequestInfo = null\n\nexport const getCodeActions = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    protocolName: string,\n    payload: any,\n): Promise<types.Command[]> => {\n    const textDocument = payload.textDocument\n    const range = payload.range\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n\n    const val = await host.getRefactors(\n        filePath,\n        range.start.line + 1,\n        range.start.character + 1,\n        range.end.line + 1,\n        range.end.character + 1,\n    )\n\n    const convertApplicableRefactorToCommand = (\n        refactor: protocol.ApplicableRefactorInfo,\n    ): types.Command[] => {\n        const actions = refactor.actions || []\n        return actions.map(action => ({\n            title: refactor.description + \": \" + action.description,\n            command: refactor.name + \"|\" + action.name,\n        }))\n    }\n\n    const arrayOfCommandArrays = val.map(refactorInfo =>\n        convertApplicableRefactorToCommand(refactorInfo),\n    )\n\n    const flattenedCommands: types.Command[] = [].concat(...arrayOfCommandArrays)\n\n    lastCodeActionRequestInfo = {\n        filePath,\n        range,\n    }\n\n    return flattenedCommands\n}\n\nexport const executeCommand = (\n    connection: LanguageConnection,\n    oni: Oni.Plugin.Api,\n    host: TypeScriptServerHost,\n) => async (protocolName: string, payload: any): Promise<any> => {\n    const command: string = payload.command\n    const args: any[] = payload.args || []\n\n    const language = Utility.getLanguageFromFileName(lastCodeActionRequestInfo.filePath)\n    const [refactorName, actionName] = command.split(\"|\")\n\n    const val = await host.getEditsForRefactor(\n        refactorName,\n        actionName,\n        lastCodeActionRequestInfo.filePath,\n        lastCodeActionRequestInfo.range.start.line + 1,\n        lastCodeActionRequestInfo.range.start.character + 1,\n        lastCodeActionRequestInfo.range.end.line + 1,\n        lastCodeActionRequestInfo.range.end.character + 1,\n    )\n\n    const changes = val.edits.reduce((prev: any, codeEdit: protocol.FileCodeEdits) => {\n        const file = oni.language.wrapPathInFileUri(codeEdit.fileName)\n        return {\n            ...prev,\n            [file]: codeEdit.textChanges.map(te => Utility.convertCodeEditToTextEdit(te)),\n        } as any\n    }, {})\n\n    await connection.request(\"workspace/applyEdit\", language, { edit: { changes } })\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Completion.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { ITextDocumentPositionParams } from \"./Types\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\nimport * as Utility from \"./Utility\"\n\nlet lastMeetInfo = null\n\nexport const getCompletions = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: ITextDocumentPositionParams,\n): Promise<types.CompletionItem[]> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const oneBasedPosition: types.Position = Utility.zeroBasedPositionToOneBasedPosition(\n        payload.position,\n    )\n\n    lastMeetInfo = {\n        filePath,\n        line: oneBasedPosition.line,\n        character: oneBasedPosition.character,\n    }\n\n    const val = await host.getCompletions(\n        filePath,\n        oneBasedPosition.line,\n        oneBasedPosition.character,\n        \"\",\n    )\n\n    const results = val.map(v => ({\n        label: v.name,\n        kind: convertTypeScriptKindToCompletionItemKind(v.kind),\n    }))\n\n    return results\n}\n\nexport const getCompletionDetails = (host: TypeScriptServerHost) => async (\n    requestName: string,\n    completionItem: types.CompletionItem,\n): Promise<types.CompletionItem> => {\n    if (!lastMeetInfo || !completionItem) {\n        return null\n    }\n\n    const details = await host.getCompletionDetails(\n        lastMeetInfo.filePath,\n        lastMeetInfo.line,\n        lastMeetInfo.character,\n        [completionItem.label],\n    )\n\n    const entry = details[0]\n\n    if (!entry) {\n        return null\n    }\n\n    return {\n        kind: convertTypeScriptKindToCompletionItemKind(entry.kind),\n        label: entry.name,\n        documentation:\n            entry.documentation && entry.documentation.length ? entry.documentation[0].text : null,\n        detail: Utility.convertToDisplayString(entry.displayParts),\n    }\n}\n\nconst convertTypeScriptKindToCompletionItemKind = (kind: string): types.CompletionItemKind => {\n    const typeScriptKindToCompletionKind = {\n        let: types.CompletionItemKind.Variable,\n        interface: types.CompletionItemKind.Interface,\n        alias: types.CompletionItemKind.Reference,\n        color: types.CompletionItemKind.Color,\n        const: types.CompletionItemKind.Value,\n        constructor: types.CompletionItemKind.Constructor,\n        class: types.CompletionItemKind.Class,\n        type: types.CompletionItemKind.Class,\n        directory: types.CompletionItemKind.File,\n        file: types.CompletionItemKind.File,\n        script: types.CompletionItemKind.File,\n        var: types.CompletionItemKind.Variable,\n        property: types.CompletionItemKind.Property,\n        parameter: types.CompletionItemKind.Variable,\n        module: types.CompletionItemKind.Module,\n        \"external module name\": types.CompletionItemKind.Module,\n        method: types.CompletionItemKind.Method,\n        function: types.CompletionItemKind.Function,\n        unit: types.CompletionItemKind.Unit,\n        keyword: types.CompletionItemKind.Keyword,\n        text: types.CompletionItemKind.Text,\n    }\n\n    if (kind && typeScriptKindToCompletionKind[kind]) {\n        return typeScriptKindToCompletionKind[kind]\n    } else {\n        return null\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Definition.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\n\nexport const getDefinition = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    protocolName: string,\n    payload: any,\n): Promise<types.Location> => {\n    const textDocument: types.TextDocument = payload.textDocument\n    const position: types.Position = payload.position\n\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const val: any = await host.getDefinition(filePath, position.line + 1, position.character + 1)\n\n    const resultPos = val[0]\n\n    if (!resultPos) {\n        return null\n    }\n\n    const range = types.Range.create(\n        resultPos.start.line - 1,\n        resultPos.start.offset - 1,\n        resultPos.end.line - 1,\n        resultPos.end.offset - 1,\n    )\n\n    return {\n        uri: oni.language.wrapPathInFileUri(resultPos.file),\n        range,\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/FindAllReferences.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\n\nexport const findAllReferences = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: any,\n): Promise<types.Location[]> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const zeroBasedPosition: types.Position = payload.position\n\n    const oneBasedPosition = {\n        line: zeroBasedPosition.line + 1,\n        column: zeroBasedPosition.character + 1,\n    }\n\n    const val = await host.findAllReferences(\n        filePath,\n        oneBasedPosition.line,\n        oneBasedPosition.column,\n    )\n\n    const mapResponseToLocation = (\n        referenceItem: protocol.ReferencesResponseItem,\n    ): types.Location => {\n        const startPosition = types.Position.create(\n            referenceItem.start.line - 1,\n            referenceItem.start.offset - 1,\n        )\n        const endPosition = types.Position.create(\n            referenceItem.end.line - 1,\n            referenceItem.end.offset - 1,\n        )\n        const range = types.Range.create(startPosition, endPosition)\n\n        return {\n            uri: oni.language.wrapPathInFileUri(referenceItem.file),\n            range,\n        }\n    }\n\n    return val.refs.map(v => mapResponseToLocation(v))\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Formatting.ts",
    "content": "/**\n * Formatting.ts\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { IDocumentRangeFormattingParams } from \"./Types\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\nimport * as Utility from \"./Utility\"\n\nexport const formatRange = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: IDocumentRangeFormattingParams,\n): Promise<types.TextEdit[]> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n\n    const startPosition: types.Position = Utility.zeroBasedPositionToOneBasedPosition(\n        payload.range.start,\n    )\n    const endPosition: types.Position = Utility.zeroBasedPositionToOneBasedPosition(\n        payload.range.end,\n    )\n\n    const val = await host.getFormattingEdits(\n        filePath,\n        startPosition.line,\n        startPosition.character,\n        endPosition.line,\n        endPosition.character,\n    )\n\n    if (!val) {\n        throw new Error(\"No edits.\")\n    }\n\n    return val.map(edit => Utility.convertCodeEditToTextEdit(edit))\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/LightweightLanguageClient.ts",
    "content": "/**\n * LightweightLanguageClient.ts\n *\n * Helper class for an in-proc strategy for implementing a language client interface\n */\n\n// TODO: Move this to Oni core, so that it can be leveraged as part of the API surface\n// (for lightweight completion scenarios, etc)\n\nexport type ServerRequestHandler = (requestName: string, payload: any) => Promise<any>\nexport type ClientRequestHandler = (payload: any) => Promise<any>\nexport type NotificationHandler = (notificationName: string, payload: any) => void\n\nimport { Event } from \"oni-types\"\n\nexport class LanguageConnection {\n    constructor(private _client: LightweightLanguageClient) {}\n\n    public request(requestName: string, language: string, payload: any): Promise<any> {\n        return this._client._getClientRequestHandler(requestName)({\n            language,\n            payload,\n        })\n    }\n\n    public notify(notificationName: string, language: string, payload: any) {\n        this._client._notify(notificationName, language, payload)\n    }\n\n    public subscribeToNotification(\n        notificationName: string,\n        notificationHandler: NotificationHandler,\n    ): void {\n        this._client._handleNotification(notificationName, notificationHandler)\n    }\n    public subscribeToRequest(requestName: string, handler: ServerRequestHandler): void {\n        this._client._handleRequest(requestName, handler)\n    }\n}\n\nexport class LightweightLanguageClient {\n    private _subscriptions: { [key: string]: Event<any> } = {}\n\n    // This is confusing because the requests are handled both ways...\n    // This dictionary tracks handlers on the 'server' side\n    private _requestHandler: { [key: string]: ServerRequestHandler } = {}\n\n    private _clientRequestHandler: { [key: string]: ClientRequestHandler } = {}\n\n    private _notificationHandler: { [key: string]: NotificationHandler } = {}\n\n    public get connection(): LanguageConnection {\n        return\n    }\n\n    public get serverCapabilities(): any {\n        return {\n            textDocumentSync: 2 /* incremental */,\n            hoverProvider: true,\n            completionProvider: {\n                resolveProvider: true,\n                triggerCharacters: [\".\"],\n            },\n            signatureHelpProvider: {\n                triggerCharacters: [\"(\"],\n            },\n            definitionProvider: true,\n            referencesProvider: true,\n            formattingProvider: false,\n            renameProvider: true,\n            documentRangeFormattingProvider: true,\n\n            // TODO:\n            // codelensprovider\n            // codeactionprovider\n            // renameprovider\n            // documentformattingprovider\n        }\n    }\n\n    public subscribe(notificationName: string, evt: Event<any>) {\n        this._subscriptions[notificationName] = evt\n    }\n\n    public async sendRequest<T>(\n        fileName: string,\n        requestName: string,\n        protocolArguments: any,\n    ): Promise<T> {\n        const handler = this._requestHandler[requestName]\n\n        const unwrappedValue = await this._unwrapThunk(protocolArguments)\n\n        if (handler) {\n            return handler(requestName, unwrappedValue)\n        } else {\n            return Promise.reject(\"Not implemented\")\n        }\n    }\n\n    public async sendNotification(\n        fileName: string,\n        notificationName: string,\n        protocolArguments: any,\n    ): Promise<void> {\n        const notifier = this._notificationHandler[notificationName]\n\n        const unwrappedValue = await this._unwrapThunk(protocolArguments)\n\n        if (notifier) {\n            notifier(notificationName, unwrappedValue)\n        }\n    }\n\n    public handleRequest(requestName: string, handler: ClientRequestHandler): void {\n        this._clientRequestHandler[requestName] = handler\n    }\n\n    public _handleRequest(requestName: string, handler: ServerRequestHandler): void {\n        this._requestHandler[requestName] = handler\n    }\n\n    public _getClientRequestHandler(requestName): ClientRequestHandler {\n        return this._clientRequestHandler[requestName]\n    }\n\n    public _handleNotification(\n        notificationName: string,\n        notificationHandler: NotificationHandler,\n    ): void {\n        this._notificationHandler[notificationName] = notificationHandler\n    }\n\n    public _notify(notificationName: string, language: string, payload: any): void {\n        const notifierEvent = this._subscriptions[notificationName]\n\n        if (notifierEvent) {\n            ;(notifierEvent as any).dispatch({\n                language, // TODO: Generalize for JS too\n                payload,\n            })\n        }\n    }\n\n    private _unwrapThunk(valueOrThunk?: any): Promise<any> {\n        if (typeof valueOrThunk !== \"function\") {\n            return valueOrThunk\n        } else {\n            const val = valueOrThunk(this.serverCapabilities)\n\n            if (!val) {\n                return Promise.resolve(val)\n            } else if (typeof val.then === \"function\") {\n                return val\n            } else {\n                return Promise.resolve(val)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/QuickInfo.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\n\nexport const getQuickInfo = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    protocolName: string,\n    payload: any,\n): Promise<types.Hover> => {\n    const textDocument: types.TextDocument = payload.textDocument\n    const position: types.Position = payload.position\n\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const val = await host.getQuickInfo(filePath, position.line + 1, position.character + 1)\n\n    return {\n        contents: [val.displayString, val.documentation],\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Rename.ts",
    "content": "/**\n * Rename.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { IRenameParams } from \"./Types\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\nimport * as Utility from \"./Utility\"\n\nexport const doRename = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: IRenameParams,\n): Promise<types.WorkspaceEdit> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const oneBasedPosition: types.Position = Utility.zeroBasedPositionToOneBasedPosition(\n        payload.position,\n    )\n\n    const val = await host.rename(filePath, oneBasedPosition.line, oneBasedPosition.character)\n\n    if (!val || !val.info.canRename) {\n        throw new Error(\"Unable to rename.\")\n    }\n\n    const mapLocsToTextEdit = (textSpan: protocol.TextSpan): types.TextEdit => {\n        const range = types.Range.create(\n            textSpan.start.line - 1,\n            textSpan.start.offset - 1,\n            textSpan.end.line - 1,\n            textSpan.end.offset - 1,\n        )\n        const newText = payload.newName\n\n        return {\n            range,\n            newText,\n        }\n    }\n\n    return val.locs.reduce<any>((previousValue, currentValue) => {\n        return {\n            ...previousValue,\n            [oni.language.wrapPathInFileUri(currentValue.file)]: currentValue.locs.map(l =>\n                mapLocsToTextEdit(l),\n            ),\n        }\n    }, {})\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/SignatureHelp.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { getCompletions } from \"./Completion\"\nimport { LightweightLanguageClient } from \"./LightweightLanguageClient\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\n\nimport { ITextDocumentPositionParams } from \"./Types\"\nimport * as Utility from \"./Utility\"\n\nexport const getSignatureHelp = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: any,\n): Promise<types.SignatureHelp> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const oneBasedPosition: types.Position = Utility.zeroBasedPositionToOneBasedPosition(\n        payload.position,\n    )\n\n    const result = await host.getSignatureHelp(\n        filePath,\n        oneBasedPosition.line,\n        oneBasedPosition.character,\n    )\n\n    const items = result.items || []\n\n    const signatureHelpItems = items.map((item): types.SignatureInformation => {\n        const prefix = Utility.convertToDisplayString(item.prefixDisplayParts)\n        const suffix = Utility.convertToDisplayString(item.suffixDisplayParts)\n        const separator = Utility.convertToDisplayString(item.separatorDisplayParts)\n\n        const parameters = item.parameters.map(p => ({\n            label: Utility.convertToDisplayString(p.displayParts),\n            documentation: Utility.convertToDisplayString(p.documentation),\n        }))\n\n        const parameterLabels = parameters.map(p => p.label)\n\n        const label = prefix + parameterLabels.join(separator) + suffix\n\n        return {\n            label,\n            documentation: Utility.convertToDisplayString(item.documentation),\n            parameters,\n        }\n    })\n\n    return {\n        signatures: signatureHelpItems,\n        activeSignature: result.selectedItemIndex,\n        activeParameter: result.argumentIndex,\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Symbols.ts",
    "content": "/**\n * Formatting.ts\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport * as Oni from \"oni-api\"\n\nimport { ISymbolSearchParams, ITextDocumentParams } from \"./Types\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\nimport * as Utility from \"./Utility\"\n\nexport const getWorkspaceSymbols = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: ISymbolSearchParams,\n): Promise<types.SymbolInformation[]> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n    const query = payload.query\n\n    if (!query) {\n        return []\n    }\n\n    const result = await host.navTo(filePath, query)\n\n    const convertNavtoItemToSymbolInformation = (\n        item: protocol.NavtoItem,\n    ): types.SymbolInformation => {\n        return {\n            name: item.name,\n            kind: Utility.convertTypeScriptKindToSymbolKind(item.kind),\n            containerName: item.containerName,\n            location: types.Location.create(\n                oni.language.wrapPathInFileUri(item.file),\n                types.Range.create(\n                    item.start.line - 1,\n                    item.start.offset - 1,\n                    item.end.line - 1,\n                    item.end.offset - 1,\n                ),\n            ),\n        }\n    }\n\n    return result.map(item => convertNavtoItemToSymbolInformation(item))\n}\n\nexport const getDocumentSymbols = (oni: Oni.Plugin.Api, host: TypeScriptServerHost) => async (\n    message: string,\n    payload: ITextDocumentParams,\n): Promise<types.SymbolInformation[]> => {\n    const textDocument: types.TextDocumentIdentifier = payload.textDocument\n    const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n\n    const items = await host.getNavigationTree(filePath)\n\n    const ret = []\n\n    const convertNavigationTreeToSymbolInformation = (\n        item: protocol.NavigationTree,\n    ): types.SymbolInformation => ({\n        name: item.text,\n        containerName: filePath,\n        kind: Utility.convertTypeScriptKindToSymbolKind(item.kind),\n        location: Utility.convertTextSpanToLocation(textDocument.uri, item.spans[0]),\n    })\n\n    const appendItemToResults = (\n        item: protocol.NavigationTree,\n        results: types.SymbolInformation[],\n    ) => {\n        results.push(convertNavigationTreeToSymbolInformation(item))\n\n        if (item.childItems) {\n            item.childItems.forEach(childItem => appendItemToResults(childItem, results))\n        }\n    }\n\n    appendItemToResults(items, ret)\n\n    return ret\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/TypeScriptConfigurationEditor.ts",
    "content": "/**\n * TypeScriptConfigurationEditor.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\nimport * as fs from \"fs\"\nimport * as path from \"path\"\n\nconst normalizePath = (str: string) => str.split(\"\\\\\").join(\"\\\\\\\\\")\n\nconst tsConfigTemplate = `\nimport * as React from \"react\"\nimport * as Oni from \"oni-api\"\n\nexport const activate = (oni: Oni.Plugin.Api) => {\n    console.log(\"config activated\")\n\n    // Input\n    //\n    // Add input bindings here:\n    //\n    oni.input.bind(\"<c-enter>\", () => console.log(\"Control+Enter was pressed\"))\n\n    //\n    // Or remove the default bindings here by uncommenting the below line:\n    //\n    // oni.input.unbind(\"<c-p>\")\n\n}\n\nexport const deactivate = (oni: Oni.Plugin.Api) => {\n    console.log(\"config deactivated\")\n}\n\nexport const configuration = {\n    //add custom config here, such as\n\n    \"ui.colorscheme\": \"nord\",\n\n    //\"oni.useDefaultConfig\": true,\n    //\"oni.bookmarks\": [\"~/Documents\"],\n    //\"oni.loadInitVim\": false,\n    //\"editor.fontSize\": \"12px\",\n    //\"editor.fontFamily\": \"Monaco\",\n\n    // UI customizations\n    \"ui.animations.enabled\": true,\n    \"ui.fontSmoothing\": \"auto\",\n}\n`\nconst getTypeScriptConfigurationFromJavaScriptConfiguration = (configurationFile: string) => {\n    const dirName = path.dirname(configurationFile)\n    const typeScriptConfig = path.join(dirName, path.basename(configurationFile, \".js\") + \".tsx\")\n\n    return typeScriptConfig\n}\n\nconst ensureTsConfig = async (typeScriptConfigFile: string, typeRoots: string): Promise<void> => {\n    if (!fs.existsSync(typeScriptConfigFile)) {\n        fs.writeFileSync(typeScriptConfigFile, tsConfigTemplate)\n    }\n    // Add a tsconfig.json file to provide completion on config\n    const tsConfig = path.join(path.dirname(typeScriptConfigFile), \"tsconfig.json\")\n    if (!fs.existsSync(tsConfig)) {\n        fs.writeFileSync(\n            tsConfig,\n            JSON.stringify(\n                {\n                    compilerOptions: {\n                        jsx: \"react\",\n                        baseUrl: typeRoots,\n                    },\n                },\n                null,\n                2,\n            ),\n        )\n    }\n}\n\nexport class TypeScriptConfigurationEditor {\n    constructor(private _mainProcessDirectory) {}\n\n    public async editConfiguration(configurationFilePath: string): Promise<string> {\n        // If a javascript configuration exists, but not a TypeScript one, we'll\n        // let the default config handle it.\n        const javaScriptConfigExists = fs.existsSync(configurationFilePath)\n        const typeScriptConfigFile = getTypeScriptConfigurationFromJavaScriptConfiguration(\n            configurationFilePath,\n        )\n        const typeScriptConfigExists = fs.existsSync(typeScriptConfigFile)\n\n        if (javaScriptConfigExists && !typeScriptConfigExists) {\n            return null\n        }\n\n        const configDirectory = path.dirname(configurationFilePath)\n\n        const typeRoots = path.join(this._mainProcessDirectory, \"node_modules\")\n\n        // Ensure that a `tsconfig.json` exists\n        // await ensureTsConfigJson(configDirectory, typeRoots)\n        await ensureTsConfig(typeScriptConfigFile, typeRoots)\n\n        return typeScriptConfigFile\n    }\n\n    public async transpileConfigurationToJavaScript(contents: string): Promise<string> {\n        const ts = await import(\"typescript\")\n        const typeRoots = path.join(this._mainProcessDirectory, \"node_modules\")\n\n        const output = ts.transpileModule(contents, {\n            reportDiagnostics: true,\n            compilerOptions: {\n                jsx: ts.JsxEmit.React,\n                baseUrl: typeRoots,\n            },\n        })\n\n        return output.outputText\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/TypeScriptServerHost.ts",
    "content": "/**\n * TypeScriptServerHost.ts\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as childProcess from \"child_process\"\nimport * as events from \"events\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\nimport * as readline from \"readline\"\n\nconst tssPath = path.join(\n    __dirname,\n    \"..\",\n    \"..\",\n    \"..\",\n    \"..\",\n    \"node_modules\",\n    \"typescript\",\n    \"lib\",\n    \"tsserver.js\",\n)\n\nexport class TypeScriptServerHost extends events.EventEmitter {\n    private _tssProcess = null\n    private _seqNumber = 0\n    private _seqToPromises = {}\n    private _rl: any\n    private _initPromise: Promise<void>\n\n    private _openedFiles: string[] = []\n\n    public get pid(): number {\n        return this._tssProcess.pid\n    }\n\n    constructor(Oni: any) {\n        super()\n        // Other tries for creating process:\n        // this._tssProcess = childProcess.spawn(\"node\", [tssPath], { stdio: \"pipe\", detached: true, shell: false });\n        // this._tssProcess = childProcess.fork(tssPath, [], { stdio: \"pipe \"})\n        //\n        // On Windows, an 'npm' window would show up, so it seems like in this context,\n        // exec was the most reliable\n\n        // Note max buffer value - once this exceeded, the process will crash\n        // TODO: Reload process, or looking at using the --eventPort option instead\n        // This has some info on using eventPort: https://github.com/Microsoft/TypeScript/blob/master/src/server/server.ts\n        // which might be more reliable\n        // Can create the port using this here: https://github.com/Microsoft/TypeScript/blob/master/src/server/server.ts\n        this._initPromise = this._startTypescriptServer(Oni)\n    }\n\n    public async _startTypescriptServer(Oni): Promise<void> {\n        this._tssProcess = await Oni.process.spawnNodeScript(tssPath)\n        console.log(\"Process ID: \" + this._tssProcess.pid) // tslint:disable-line no-console\n\n        this._rl = readline.createInterface({\n            input: this._tssProcess.stdout,\n            output: this._tssProcess.stdin,\n            terminal: false,\n        })\n\n        this._tssProcess.stderr.on(\"data\", (data, err) => {\n            console.warn(\"Error from tss: \" + data) // tslint:disable-line no-console\n        })\n\n        this._tssProcess.on(\"error\", data => {\n            debugger // tslint:disable-line no-debugger\n        })\n\n        this._tssProcess.on(\"exit\", data => {\n            debugger // tslint:disable-line no-debugger\n        })\n\n        this._tssProcess.on(\"close\", data => {\n            debugger // tslint:disable-line no-debugger\n        })\n\n        this._rl.on(\"line\", msg => {\n            if (msg.indexOf(\"{\") === 0) {\n                this._parseResponse(msg)\n            }\n        })\n    }\n\n    public async openFile(file: string, text?: string): Promise<any> {\n        if (this._openedFiles.indexOf(file) >= 0) {\n            return\n        }\n\n        this._openedFiles.push(file)\n\n        return this._makeTssRequest(\"open\", {\n            file,\n            fileContent: text,\n        })\n    }\n\n    public getProjectInfo(file: string): Promise<any> {\n        return this._makeTssRequest(\"projectInfo\", {\n            file,\n            needFileNameList: true,\n        })\n    }\n    public getDefinition(file: string, line: number, offset: number): Promise<void> {\n        return this._makeTssRequest<void>(\"definition\", {\n            file,\n            line,\n            offset,\n        })\n    }\n\n    public getTypeDefinition(file: string, line: number, offset: number): Promise<void> {\n        return this._makeTssRequest<void>(\"typeDefinition\", {\n            file,\n            line,\n            offset,\n        })\n    }\n\n    public getFormattingEdits(\n        file: string,\n        line: number,\n        offset: number,\n        endLine: number,\n        endOffset: number,\n    ): Promise<protocol.CodeEdit[]> {\n        return this._makeTssRequest<protocol.CodeEdit[]>(\"format\", {\n            file,\n            line,\n            offset,\n            endLine,\n            endOffset,\n        })\n    }\n\n    public getCompletions(\n        file: string,\n        line: number,\n        offset: number,\n        prefix: string,\n    ): Promise<any> {\n        return this._makeTssRequest<void>(\"completions\", {\n            file,\n            line,\n            offset,\n            prefix,\n        })\n    }\n\n    public getCompletionDetails(\n        file: string,\n        line: number,\n        offset: number,\n        entryNames: string[],\n    ): Promise<any> {\n        return this._makeTssRequest<void>(\"completionEntryDetails\", {\n            file,\n            line,\n            offset,\n            entryNames,\n        })\n    }\n\n    public getRefactors(\n        file: string,\n        startLine: number,\n        startOffset: number,\n        endLine: number,\n        endOffset: number,\n    ): Promise<protocol.ApplicableRefactorInfo[]> {\n        return this._makeTssRequest<protocol.ApplicableRefactorInfo[]>(\"getApplicableRefactors\", {\n            file,\n            startLine,\n            startOffset,\n            endLine,\n            endOffset,\n        })\n    }\n\n    public getEditsForRefactor(\n        refactor: string,\n        action: string,\n        file: string,\n        startLine: number,\n        startOffset: number,\n        endLine: number,\n        endOffset: number,\n    ): Promise<protocol.RefactorEditInfo> {\n        return this._makeTssRequest<protocol.RefactorEditInfo>(\"getEditsForRefactor\", {\n            refactor,\n            action,\n            file,\n            startLine,\n            startOffset,\n            endLine,\n            endOffset,\n        })\n    }\n\n    public updateFile(file: string, fileContent: string): Promise<void> {\n        const totalLines = fileContent.split(os.EOL)\n        return this._makeTssRequest<void>(\"change\", {\n            file,\n            line: 1,\n            offset: 1,\n            endLine: totalLines.length + 1,\n            endOffset: 1,\n            insertString: fileContent,\n        })\n    }\n\n    public changeLineInFile(file: string, line: number, newLineContents: string): Promise<void> {\n        return this._makeTssRequest<void>(\"change\", {\n            file,\n            line,\n            offset: 1,\n            endOffset: 1,\n            endLine: line + 1,\n            insertString: newLineContents + os.EOL,\n        })\n    }\n\n    public getQuickInfo(file: string, line: number, offset: number): Promise<any> {\n        return this._makeTssRequest<void>(\"quickinfo\", {\n            file,\n            line,\n            offset,\n        })\n    }\n\n    public saveTo(file: string, tmpfile: string): Promise<void> {\n        return this._makeTssRequest<void>(\"saveto\", {\n            file,\n            tmpfile,\n        })\n    }\n\n    public getSignatureHelp(file: string, line: number, offset: number): Promise<any> {\n        return this._makeTssRequest<void>(\"signatureHelp\", {\n            file,\n            line,\n            offset,\n        })\n    }\n\n    public getErrors(fullFilePath: string): Promise<void> {\n        return this._makeTssRequest<void>(\"geterr\", {\n            files: [fullFilePath],\n            delay: 500,\n        })\n    }\n\n    public getErrorsAcrossProject(fullFilePath: string): Promise<void> {\n        return this._makeTssRequest<void>(\"geterrForProject\", {\n            file: fullFilePath,\n        })\n    }\n\n    public getNavigationTree(fullFilePath: string): Promise<protocol.NavigationTree> {\n        return this._makeTssRequest<protocol.NavigationTree>(\"navtree\", {\n            file: fullFilePath,\n        })\n    }\n\n    public getDocumentHighlights(file: string, line: number, offset: number): Promise<void> {\n        return this._makeTssRequest<void>(\"documentHighlights\", {\n            file,\n            line,\n            offset,\n        })\n    }\n\n    public findAllReferences(\n        file: string,\n        line: number,\n        offset: number,\n    ): Promise<protocol.ReferencesResponseBody> {\n        return this._makeTssRequest<protocol.ReferencesResponseBody>(\"references\", {\n            file,\n            line,\n            offset,\n        })\n    }\n    public navTo(file: string, query: string): Promise<protocol.NavtoItem[]> {\n        return this._makeTssRequest<protocol.NavtoItem[]>(\"navto\", {\n            file,\n            searchValue: query,\n        })\n    }\n\n    public rename(\n        file: string,\n        line: number,\n        offset: number,\n    ): Promise<protocol.RenameResponseBody> {\n        return this._makeTssRequest<protocol.RenameResponseBody>(\"rename\", {\n            file,\n            line,\n            offset,\n            findInComments: false,\n            findInStrings: false,\n        })\n    }\n\n    public async _makeTssRequest<T>(commandName: string, args: any): Promise<T> {\n        await this._initPromise\n        const seq = this._seqNumber++\n        const payload = {\n            seq,\n            type: \"request\",\n            command: commandName,\n            arguments: args,\n        }\n\n        const ret = this._createDeferredPromise<T>()\n        this._seqToPromises[seq] = ret\n\n        // TODO: Handle updates in parallel?\n\n        this._tssProcess.stdin.write(JSON.stringify(payload) + os.EOL)\n\n        return ret.promise\n    }\n\n    private _parseResponse(returnedData: string): void {\n        const response = JSON.parse(returnedData)\n\n        const seq = response[\"request_seq\"] // tslint:disable-line no-string-literal\n        const success = response[\"success\"] // tslint:disable-line no-string-literal\n\n        if (typeof seq === \"number\") {\n            if (success) {\n                this._seqToPromises[seq].resolve(response.body)\n            } else {\n                this._seqToPromises[seq].reject(new Error(response.message))\n            }\n\n            this._seqToPromises[seq] = null\n        } else {\n            // If a sequence wasn't specified, it might be a call that returns multiple results\n            // Like 'geterr' - returns both semanticDiag and syntaxDiag\n            if (response.type && response.type === \"event\") {\n                if (response.event && response.event === \"semanticDiag\") {\n                    this.emit(\"semanticDiag\", response.body)\n                }\n            }\n        }\n    }\n\n    private _createDeferredPromise<T>(): any {\n        let resolve\n        let reject\n        const promise = new Promise((res, rej) => {\n            resolve = res\n            reject = rej\n        })\n        return {\n            resolve,\n            reject,\n            promise,\n        }\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Types.ts",
    "content": "/**\n * Types.ts\n *\n * Helper types\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as types from \"vscode-languageserver-types\"\n\n/**\n * IDisplayPart, coming from TSS\n */\nexport interface IDisplayPart {\n    text: string\n    kind: string\n}\n\nexport interface ITextDocumentParams {\n    textDocument: types.TextDocumentIdentifier\n}\n\nexport interface ISymbolSearchParams extends ITextDocumentParams {\n    query: string\n}\n\n/**\n * TextDocumentPosition, from LSP\n */\nexport interface ITextDocumentPositionParams extends ITextDocumentParams {\n    position: types.Position\n}\n\nexport interface IRenameParams extends ITextDocumentPositionParams {\n    newName: string\n}\n\nexport interface IDocumentRangeFormattingParams extends ITextDocumentParams {\n    textDocument: types.TextDocumentIdentifier\n    range: types.Range\n    options: types.FormattingOptions\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/Utility.ts",
    "content": "/**\n * Utility.ts\n */\n\nimport * as path from \"path\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { CodeEdit, TextSpan } from \"typescript/lib/protocol\" // tslint:disable-line\n\nimport { IDisplayPart } from \"./Types\"\n\nexport const zeroBasedPositionToOneBasedPosition = (zeroBasedPosition: types.Position) => ({\n    line: zeroBasedPosition.line + 1,\n    character: zeroBasedPosition.character + 1,\n})\n\nexport const getLanguageFromFileName = (fileName: string) => {\n    const extension = path.extname(fileName)\n    const language = extension === \".js\" || extension === \".jsx\" ? \"javascript\" : \"typescript\"\n    return language\n}\n\nexport const convertCodeEditToTextEdit = (codeEdit: CodeEdit): types.TextEdit => {\n    const range = types.Range.create(\n        codeEdit.start.line - 1,\n        codeEdit.start.offset - 1,\n        codeEdit.end.line - 1,\n        codeEdit.end.offset - 1,\n    )\n    const newText = codeEdit.newText\n\n    return {\n        range,\n        newText,\n    }\n}\n\nexport const convertToDisplayString = (displayParts: IDisplayPart[]) => {\n    let ret = \"\"\n\n    if (!displayParts || !displayParts.forEach) {\n        return ret\n    }\n\n    displayParts.forEach(dp => {\n        ret += dp.text\n    })\n\n    return ret\n}\n\nexport const convertTypeScriptKindToSymbolKind = (kind: string): types.SymbolKind => {\n    switch (kind) {\n        case \"var\":\n        case \"let\":\n            return types.SymbolKind.Variable\n        case \"property\":\n        case \"getter\":\n            return types.SymbolKind.Property\n        case \"const\":\n            return types.SymbolKind.Constant\n        case \"method\":\n            return types.SymbolKind.Method\n        case \"interface\":\n            return types.SymbolKind.Interface\n        case \"type\":\n            return types.SymbolKind.Constructor\n        case \"class\":\n            return types.SymbolKind.Class\n        case \"module\":\n            return types.SymbolKind.Module\n        case \"alias\":\n            return types.SymbolKind.Variable\n        case \"function\":\n            return types.SymbolKind.Function\n        case \"enum member\":\n            return types.SymbolKind.Enum\n        default:\n            return types.SymbolKind.Field\n    }\n}\n\nexport const convertTextSpanToRange = (span: TextSpan): types.Range => {\n    return types.Range.create(\n        span.start.line - 1,\n        span.start.offset - 1,\n        span.end.line - 1,\n        span.end.offset - 1,\n    )\n}\n\nexport const convertTextSpanToLocation = (\n    fileUri: string,\n    span: protocol.TextSpan,\n): types.Location => {\n    const range = convertTextSpanToRange(span)\n    return types.Location.create(fileUri, range)\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/src/index.ts",
    "content": "/**\n * index.ts\n *\n * Entry point for ONI's TypeScript Language Service integraiton\n */\n\n/// <reference path=\"./../../../../node_modules/typescript/lib/protocol.d.ts\" />\n\nimport * as os from \"os\"\nimport * as path from \"path\"\n\nimport * as Oni from \"oni-api\"\n\nimport * as types from \"vscode-languageserver-types\"\n\nimport { executeCommand, getCodeActions } from \"./CodeActions\"\nimport { getCompletionDetails, getCompletions } from \"./Completion\"\nimport { getDefinition } from \"./Definition\"\nimport { findAllReferences } from \"./FindAllReferences\"\nimport { formatRange } from \"./Formatting\"\nimport { LanguageConnection, LightweightLanguageClient } from \"./LightweightLanguageClient\"\nimport { getQuickInfo } from \"./QuickInfo\"\nimport { doRename } from \"./Rename\"\nimport { getSignatureHelp } from \"./SignatureHelp\"\nimport { getDocumentSymbols, getWorkspaceSymbols } from \"./Symbols\"\nimport { TypeScriptConfigurationEditor } from \"./TypeScriptConfigurationEditor\"\nimport { TypeScriptServerHost } from \"./TypeScriptServerHost\"\nimport * as Utility from \"./Utility\"\n\nexport const activate = (oni: Oni.Plugin.Api) => {\n    let _host: TypeScriptServerHost = null\n\n    const anyConfig = oni.configuration as any\n    const anyProcess = oni.process as any\n\n    // Add typescript as an editor\n    anyConfig.registerEditor(\n        \"typescript\",\n        new TypeScriptConfigurationEditor(anyProcess.getDirname()),\n    )\n\n    const initializeHost = (host: TypeScriptServerHost) => {\n        host.on(\"semanticDiag\", diagnostics => {\n            const fileName = diagnostics.file\n\n            const diags = diagnostics.diagnostics || []\n\n            const errors = diags.map(d => {\n                // Convert lines to zero-based to accomodate protocol\n                const startPosition = types.Position.create(d.start.line - 1, d.start.offset - 1)\n                const endPosition = types.Position.create(d.end.line - 1, d.end.offset - 1)\n                const range = types.Range.create(startPosition, endPosition)\n\n                const ret: types.Diagnostic = {\n                    // type: null,\n                    code: d.code,\n                    message: d.text,\n                    range,\n                    severity: types.DiagnosticSeverity.Error,\n                }\n                return ret\n            })\n\n            const language = Utility.getLanguageFromFileName(fileName)\n\n            connection.notify(\"textDocument/publishDiagnostics\", language, {\n                uri: oni.language.wrapPathInFileUri(fileName),\n                diagnostics: errors,\n            })\n        })\n\n        connection.subscribeToRequest(\"completionItem/resolve\", getCompletionDetails(host))\n\n        connection.subscribeToNotification(\"textDocument/didChange\", protocolChangeFile(host))\n        connection.subscribeToNotification(\"textDocument/didSave\", onSaved(host))\n\n        connection.subscribeToRequest(\"textDocument/completion\", getCompletions(oni, host))\n        connection.subscribeToRequest(\"textDocument/codeAction\", getCodeActions(oni, host))\n        connection.subscribeToRequest(\"textDocument/definition\", getDefinition(oni, host))\n        connection.subscribeToRequest(\"textDocument/hover\", getQuickInfo(oni, host))\n        connection.subscribeToRequest(\"textDocument/rangeFormatting\", formatRange(oni, host))\n        connection.subscribeToRequest(\"textDocument/references\", findAllReferences(oni, host))\n        connection.subscribeToRequest(\"textDocument/rename\", doRename(oni, host))\n        connection.subscribeToRequest(\"textDocument/signatureHelp\", getSignatureHelp(oni, host))\n        connection.subscribeToRequest(\"textDocument/documentSymbol\", getDocumentSymbols(oni, host))\n\n        connection.subscribeToRequest(\n            \"workspace/executeCommand\",\n            executeCommand(connection, oni, host),\n        )\n        connection.subscribeToRequest(\"workspace/symbol\", getWorkspaceSymbols(oni, host))\n    }\n\n    const getHost = () => {\n        if (!_host) {\n            _host = new TypeScriptServerHost(oni)\n            initializeHost(_host)\n        }\n\n        return _host\n    }\n\n    const _lightweightLanguageClient = new LightweightLanguageClient()\n    const jsLspCommand = oni.configuration.getValue(\"language.javascript.languageServer.command\")\n    const jsLspArgs = oni.configuration.getValue(\"language.javascript.languageServer.arguments\")\n    const tsLspCommand = oni.configuration.getValue(\"language.typescript.languageServer.command\")\n    const tsLspArgs = oni.configuration.getValue(\"language.typescript.languageServer.arguments\")\n    const existingJsLSP = !!(jsLspCommand || jsLspArgs)\n    const existingTsLSP = !!(tsLspCommand || tsLspArgs)\n\n    if (!existingJsLSP) {\n        oni.language.registerLanguageClient(\"javascript\", _lightweightLanguageClient)\n    }\n    if (!existingTsLSP) {\n        oni.language.registerLanguageClient(\"typescript\", _lightweightLanguageClient)\n    }\n\n    const connection = new LanguageConnection(_lightweightLanguageClient)\n\n    // Subscribe to textDocument/didOpen initially, to kick off\n    // initialization of the language server\n\n    const protocolOpenFile = (message: string, payload: any) => {\n        const textDocument: any = payload.textDocument\n        const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n\n        getHost().openFile(filePath, textDocument.text)\n    }\n    connection.subscribeToNotification(\"textDocument/didOpen\", protocolOpenFile)\n\n    const isSingleLineChange = (range: types.Range): boolean => {\n        if (range.start.line === range.end.line) {\n            return true\n        }\n\n        if (\n            range.start.character === 0 &&\n            range.end.character === 0 &&\n            range.start.line + 1 === range.end.line\n        ) {\n            return true\n        }\n\n        return false\n    }\n\n    const removeNewLines = (str: string) => {\n        return str.replace(/(\\r\\n|\\n|\\r)/gm, \"\")\n    }\n\n    const protocolChangeFile = (host: TypeScriptServerHost) => async (\n        message: string,\n        payload: any,\n    ) => {\n        const textDocument: types.TextDocumentIdentifier = payload.textDocument\n        const contentChanges: types.TextDocumentContentChangeEvent[] = payload.contentChanges\n\n        if (!contentChanges || !contentChanges.length) {\n            return\n        }\n\n        if (contentChanges.length > 1) {\n            oni.log.warn(\"Only handling first content change\")\n        }\n\n        const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n\n        const change = contentChanges[0]\n        if (!change.range) {\n            host.updateFile(filePath, change.text)\n        } else if (isSingleLineChange(change.range) && change.text) {\n            host.changeLineInFile(\n                filePath,\n                change.range.start.line + 1,\n                removeNewLines(change.text),\n            )\n        } else {\n            oni.log.warn(\"Unhandled change request!\")\n        }\n\n        const saveFile = oni.configuration.getValue<string>(\"debug.typescript.saveFile\")\n        if (saveFile) {\n            host.saveTo(filePath, saveFile)\n        }\n\n        // Update errors for modified file\n        host.getErrors(filePath)\n    }\n\n    const onSaved = (host: TypeScriptServerHost) => (protocolName: string, payload: any) => {\n        const textDocument = payload.textDocument\n        const filePath = oni.language.unwrapFileUriPath(textDocument.uri)\n        host.getErrorsAcrossProject(filePath)\n    }\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"lib\": [\"dom\", \"es2017\"],\n        \"module\": \"commonjs\",\n        \"preserveConstEnums\": true,\n        \"outDir\": \"./lib\",\n        \"declaration\": true,\n        \"sourceMap\": true,\n        \"target\": \"ES5\",\n        \"types\": []\n    },\n    \"include\": [\"src/**/*.ts\"],\n    \"exclude\": [\"node_modules\", \"typings/browser.d.ts\", \"typings/browser\", \"ui-tests\"]\n}\n"
  },
  {
    "path": "vim/core/oni-plugin-typescript/tsconfig.test.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"preserveConstEnums\": true,\n        \"outDir\": \"./lib_test\",\n        \"declaration\": true,\n        \"sourceMap\": true,\n        \"target\": \"ES5\"\n    },\n    \"include\": [\"test/**/*.ts\", \"src/**/*.ts\"],\n    \"exclude\": [\"node_modules\", \"typings/browser.d.ts\", \"typings/browser\"]\n}\n"
  },
  {
    "path": "vim/default/bundle/oni-vim-defaults/plugin/init.vim",
    "content": "set number\nset noswapfile\nset smartcase\n\nset splitright\nset splitbelow\n\n\" Turn off statusbar, because it is externalized\nset noshowmode\nset noruler\nset laststatus=0\nset noshowcmd\n\n\" Enable GUI mouse behavior\nset mouse=a\n\n\" All config settings after this point \n\" can be removed, once an Oni config option is added.\n\n\" Use ESC to exit insert mode in :term\ntnoremap <Esc> <C-\\><C-n>\n\n\" Default tab settings\nset tabstop=4\nset shiftwidth=4\nset softtabstop=4\nset expandtab\n"
  },
  {
    "path": "vim/noop.vim",
    "content": "echom \"Welcome to Oni\"\n"
  },
  {
    "path": "webview_preload/src/index.ts",
    "content": "/**\n * Entry point for 'sneak integration' + Oni augmentations in the browser\n *\n * This script is a 'preload' script for the webview. You can see more info here:\n * https://electronjs.org/docs/api/webview-tag#preload\n */\n\ndeclare var require: any\n;(() => {\n    const __oni_win: any = window\n\n    const { ipcRenderer } = require(\"electron\")\n\n    window.document.addEventListener(\"focusin\", evt => {\n        const target = evt.target as HTMLElement\n        ipcRenderer.sendToHost(\"focusin\", target ? target.tagName : null)\n    })\n\n    window.document.addEventListener(\"focusout\", evt => {\n        ipcRenderer.sendToHost(\"focusout\")\n    })\n\n    interface Rectangle {\n        x: number\n        y: number\n        width: number\n        height: number\n    }\n\n    const createRectangle = (x: number, y: number, width: number, height: number): Rectangle => ({\n        x,\n        y,\n        width,\n        height,\n    })\n\n    interface OniTagInfo {\n        id: string\n        callback: () => void\n        rectangle: Rectangle\n    }\n\n    let _tags: OniTagInfo[] = []\n\n    // Note that this name must be in sync with 'BrowserView.tsx'\n    __oni_win[\"__oni_sneak_collector__\"] = () => {\n        _tags = []\n        let idx = 0\n\n        const width = window.innerWidth\n        const height = window.innerHeight\n\n        const addElement = (element: HTMLElement): void => {\n            idx++\n            const clientRect = element.getBoundingClientRect()\n\n            if (clientRect.width === 0 || clientRect.height === 0) {\n                return\n            }\n\n            const isInBounds =\n                clientRect.top >= 0 &&\n                clientRect.left >= 0 &&\n                clientRect.top <= height &&\n                clientRect.left <= width\n\n            if (!isInBounds) {\n                return\n            }\n\n            const callback = (elem: HTMLElement) => () => {\n                if (elem && elem.click) {\n                    if (elem.tagName === \"A\") {\n                        elem.click()\n                    } else if (elem.tagName === \"INPUT\" || elem.tagName === \"TEXTAREA\") {\n                        elem.focus()\n                    }\n                }\n            }\n\n            _tags.push({\n                rectangle: createRectangle(\n                    clientRect.left,\n                    clientRect.top,\n                    clientRect.width,\n                    clientRect.height,\n                ),\n                id: idx.toString(),\n                callback: callback(element),\n            })\n        }\n\n        const tagsToCollect = [\"a\", \"input\", \"textarea\"]\n\n        tagsToCollect.forEach(tag => {\n            const elems = document.getElementsByTagName(tag) as HTMLCollectionOf<HTMLElement>\n\n            for (let i = 0; i < elems.length; i++) {\n                addElement(elems[i])\n            }\n        })\n\n        const ret = _tags.map(tag => ({\n            id: tag.id,\n            rectangle: tag.rectangle,\n        }))\n        return ret\n    }\n\n    __oni_win[\"__oni_sneak_execute__\"] = (id: string) => {\n        const matchingTags = _tags.filter(t => t.id === id)\n\n        if (matchingTags.length > 0) {\n            const match = matchingTags[0]\n            match.callback()\n        }\n    }\n})()\n"
  },
  {
    "path": "webview_preload/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        /* Basic Options */\n        \"target\":\n            \"es5\" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */,\n        \"module\":\n            \"commonjs\" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,\n        \"outDir\": \"../lib/webview_preload\",\n        // \"lib\": [],                             /* Specify library files to be included in the compilation:  */\n        // \"allowJs\": true,                       /* Allow javascript files to be compiled. */\n        // \"checkJs\": true,                       /* Report errors in .js files. */\n        // \"jsx\": \"preserve\",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */\n        // \"declaration\": true,                   /* Generates corresponding '.d.ts' file. */\n        // \"sourceMap\": true,                     /* Generates corresponding '.map' file. */\n        // \"outFile\": \"./\",                       /* Concatenate and emit output to single file. */\n        // \"outDir\": \"./\",                        /* Redirect output structure to the directory. */\n        // \"rootDir\": \"./\",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */\n        // \"removeComments\": true,                /* Do not emit comments to output. */\n        // \"noEmit\": true,                        /* Do not emit outputs. */\n        // \"importHelpers\": true,                 /* Import emit helpers from 'tslib'. */\n        // \"downlevelIteration\": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */\n        // \"isolatedModules\": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */\n\n        /* Strict Type-Checking Options */\n        \"strict\": true /* Enable all strict type-checking options. */,\n        \"types\": [\"mocha\"]\n        // \"noImplicitAny\": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */\n        // \"strictNullChecks\": true,              /* Enable strict null checks. */\n        // \"strictFunctionTypes\": true,           /* Enable strict checking of function types. */\n        // \"noImplicitThis\": true,                /* Raise error on 'this' expressions with an implied 'any' type. */\n        // \"alwaysStrict\": true,                  /* Parse in strict mode and emit \"use strict\" for each source file. */\n\n        /* Additional Checks */\n        // \"noUnusedLocals\": true,                /* Report errors on unused locals. */\n        // \"noUnusedParameters\": true,            /* Report errors on unused parameters. */\n        // \"noImplicitReturns\": true,             /* Report error when not all code paths in function return a value. */\n        // \"noFallthroughCasesInSwitch\": true,    /* Report errors for fallthrough cases in switch statement. */\n\n        /* Module Resolution Options */\n        // \"moduleResolution\": \"node\",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */\n        // \"baseUrl\": \"./\",                       /* Base directory to resolve non-absolute module names. */\n        // \"paths\": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */\n        // \"rootDirs\": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */\n        // \"typeRoots\": [],                       /* List of folders to include type definitions from. */\n        // \"types\": [],                           /* Type declaration files to be included in compilation. */\n        // \"allowSyntheticDefaultImports\": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */\n        // \"preserveSymlinks\": true,              /* Do not resolve the real path of symlinks. */\n\n        /* Source Map Options */\n        // \"sourceRoot\": \"./\",                    /* Specify the location where debugger should locate TypeScript files instead of source locations. */\n        // \"mapRoot\": \"./\",                       /* Specify the location where debugger should locate map files instead of generated locations. */\n        // \"inlineSourceMap\": true,               /* Emit a single file with source maps instead of having a separate file. */\n        // \"inlineSources\": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */\n\n        /* Experimental Options */\n        // \"experimentalDecorators\": true,        /* Enables experimental support for ES7 decorators. */\n        // \"emitDecoratorMetadata\": true,         /* Enables experimental support for emitting type metadata for decorators. */\n    },\n    \"include\": [\"src/**/*.ts\"],\n    \"exclude\": [\"node_modules\"]\n}\n"
  }
]