Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c (#8525)

* Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c

* remove files we don't want

* fix hygiene

* update distro

* update distro

* fix hygiene

* fix strict nulls

* distro

* distro

* fix tests

* fix tests

* add another edit

* fix viewlet icon

* fix azure dialog

* fix some padding

* fix more padding issues
This commit is contained in:
Anthony Dresser
2019-12-04 19:28:22 -08:00
committed by GitHub
parent a8818ab0df
commit f5ce7fb2a5
1507 changed files with 42813 additions and 27370 deletions
+1 -1
View File
@@ -74,7 +74,7 @@
"vscode-nls": "^3.2.1"
},
"devDependencies": {
"@types/node": "10",
"@types/node": "^12.11.7",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.3",
+4 -4
View File
@@ -2,10 +2,10 @@
# yarn lockfile v1
"@types/node@10":
version "10.17.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.4.tgz#8993a4fe3c4022fda66bf4ea660d615fc5659c6f"
integrity sha512-F2pgg+LcIr/elguz+x+fdBX5KeZXGUOp7TV8M0TVIrDezYLFRNt8oMTyps0VQ1kj5WGGoR18RdxnRDHXrIFHMQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
"ads-extension-telemetry@github:Charles-Gagnon/ads-extension-telemetry#0.1.0":
version "0.1.0"
+1 -1
View File
@@ -82,7 +82,7 @@
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^10.14.8",
"@types/node": "^12.11.7",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
+4 -4
View File
@@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.6.tgz#b8622d50557dd155e9f2f634b7d68fd38de5e94b"
integrity sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==
"@types/node@^10.14.8":
version "10.14.17"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.17.tgz#b96d4dd3e427382482848948041d3754d40fd5ce"
integrity sha512-p/sGgiPaathCfOtqu2fx5Mu1bcjuP8ALFg4xpGgNkcin7LwRyzUKniEHBKdcE1RPsenq5JVPIpMTJSygLboygQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
+1 -1
View File
@@ -186,7 +186,7 @@
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.12",
"@types/node": "^12.11.7",
"@types/request": "^2.48.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
+6 -1
View File
@@ -59,11 +59,16 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073"
integrity sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==
"@types/node@*", "@types/node@^10.12.12":
"@types/node@*":
version "10.14.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.4.tgz#1c586b991457cbb58fef51bc4e0cfcfa347714b5"
integrity sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
"@types/node@^8.0.47":
version "8.10.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.45.tgz#4c49ba34106bc7dced77ff6bae8eb6543cde8351"
+1 -1
View File
@@ -633,7 +633,7 @@
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^10.14.8",
"@types/node": "^12.11.7",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"mocha": "^5.2.0",
+4 -4
View File
@@ -7,10 +7,10 @@
resolved "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073"
integrity sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==
"@types/node@^10.14.8":
version "10.14.17"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.17.tgz#b96d4dd3e427382482848948041d3754d40fd5ce"
integrity sha512-p/sGgiPaathCfOtqu2fx5Mu1bcjuP8ALFg4xpGgNkcin7LwRyzUKniEHBKdcE1RPsenq5JVPIpMTJSygLboygQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
ajv@^5.3.0:
version "5.5.2"
@@ -38,7 +38,8 @@
"tasks.json",
"keybindings.json",
"extensions.json",
"argv.json"
"argv.json",
"profiles.json"
]
}
],
@@ -114,6 +115,6 @@
]
},
"devDependencies": {
"@types/node": "^10.14.8"
"@types/node": "^12.11.7"
}
}
@@ -18,6 +18,20 @@
"type": "integer"
}
},
"remoteEnv": {
"type": "object",
"additionalProperties": {
"type": [
"string",
"null"
]
},
"description": "Remote environment variables."
},
"remoteUser": {
"type": "string",
"description": "The user VS Code Server will be started with. The default is the same user as the container."
},
"extensions": {
"type": "array",
"description": "An array of extensions that should be installed into the container.",
@@ -22,6 +22,20 @@
"$ref": "vscode://schemas/settings/machine",
"description": "Machine specific settings that should be copied into the container."
},
"remoteEnv": {
"type": "object",
"additionalProperties": {
"type": [
"string",
"null"
]
},
"description": "Remote environment variables."
},
"remoteUser": {
"type": "string",
"description": "The user VS Code Server will be started with. The default is the same user as the container."
},
"postCreateCommand": {
"type": [
"string",
@@ -55,6 +69,21 @@
]
}
},
"containerEnv": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Container environment variables."
},
"containerUser": {
"type": "string",
"description": "The user the container will be started with. The default is the user on the Docker image."
},
"updateRemoteUserUID": {
"type": "boolean",
"description": "Controls whether on Linux the container's user should be updated with the local user's UID and GID. On by default."
},
"runArgs": {
"type": "array",
"description": "The arguments required when starting in the container.",
@@ -68,7 +97,7 @@
"none",
"stopContainer"
],
"description": "Action to take when VS Code is shutting down. The default is to stop the container."
"description": "Action to take when the VS Code window is closed. The default is to stop the container."
},
"overrideCommand": {
"type": "boolean",
@@ -146,7 +175,7 @@
"none",
"stopCompose"
],
"description": "Action to take when VS Code is shutting down. The default is to stop the containers."
"description": "Action to take when the VS Code window is closed. The default is to stop the containers."
}
},
"required": [
@@ -4,23 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import { getLocation, parse, visit } from 'jsonc-parser';
import * as path from 'path';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { SettingsDocument } from './settingsDocumentHelper';
const localize = nls.loadMessageBundle();
const fadedDecoration = vscode.window.createTextEditorDecorationType({
light: {
color: '#757575'
},
dark: {
color: '#878787'
}
});
let pendingLaunchJsonDecoration: NodeJS.Timer;
export function activate(context: vscode.ExtensionContext): void {
//settings.json suggestions
context.subscriptions.push(registerSettingsCompletions());
@@ -33,18 +21,6 @@ export function activate(context: vscode.ExtensionContext): void {
// task.json variable suggestions
context.subscriptions.push(registerVariableCompletions('**/tasks.json'));
// launch.json decorations
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => updateLaunchJsonDecorations(editor), null, context.subscriptions));
context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(event => {
if (vscode.window.activeTextEditor && event.document === vscode.window.activeTextEditor.document) {
if (pendingLaunchJsonDecoration) {
clearTimeout(pendingLaunchJsonDecoration);
}
pendingLaunchJsonDecoration = setTimeout(() => updateLaunchJsonDecorations(vscode.window.activeTextEditor), 1000);
}
}, null, context.subscriptions));
updateLaunchJsonDecorations(vscode.window.activeTextEditor);
}
function registerSettingsCompletions(): vscode.Disposable {
@@ -153,39 +129,6 @@ function provideInstalledExtensionProposals(extensionsContent: IExtensionsConten
return undefined;
}
function updateLaunchJsonDecorations(editor: vscode.TextEditor | undefined): void {
if (!editor || path.basename(editor.document.fileName) !== 'launch.json') {
return;
}
const ranges: vscode.Range[] = [];
let addPropertyAndValue = false;
let depthInArray = 0;
visit(editor.document.getText(), {
onObjectProperty: (property, offset, length) => {
// Decorate attributes which are unlikely to be edited by the user.
// Only decorate "configurations" if it is not inside an array (compounds have a configurations property which should not be decorated).
addPropertyAndValue = property === 'version' || property === 'type' || property === 'request' || property === 'compounds' || (property === 'configurations' && depthInArray === 0);
if (addPropertyAndValue) {
ranges.push(new vscode.Range(editor.document.positionAt(offset), editor.document.positionAt(offset + length)));
}
},
onLiteralValue: (_value, offset, length) => {
if (addPropertyAndValue) {
ranges.push(new vscode.Range(editor.document.positionAt(offset), editor.document.positionAt(offset + length)));
}
},
onArrayBegin: (_offset: number, _length: number) => {
depthInArray++;
},
onArrayEnd: (_offset: number, _length: number) => {
depthInArray--;
}
});
editor.setDecorations(fadedDecoration, ranges);
}
vscode.languages.registerDocumentSymbolProvider({ pattern: '**/launch.json', language: 'jsonc' }, {
provideDocumentSymbols(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.SymbolInformation[]> {
const result: vscode.SymbolInformation[] = [];
+4 -4
View File
@@ -2,10 +2,10 @@
# yarn lockfile v1
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
jsonc-parser@^2.1.1:
version "2.1.1"
+1 -1
View File
@@ -57,7 +57,7 @@
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "10",
"@types/node": "^12.11.7",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
+4 -4
View File
@@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.6.tgz#b8622d50557dd155e9f2f634b7d68fd38de5e94b"
integrity sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==
"@types/node@10":
version "10.17.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.4.tgz#8993a4fe3c4022fda66bf4ea660d615fc5659c6f"
integrity sha512-F2pgg+LcIr/elguz+x+fdBX5KeZXGUOp7TV8M0TVIrDezYLFRNt8oMTyps0VQ1kj5WGGoR18RdxnRDHXrIFHMQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
+1 -1
View File
@@ -54,6 +54,6 @@
},
"devDependencies": {
"@types/markdown-it": "0.0.2",
"@types/node": "^10.14.8"
"@types/node": "^12.11.7"
}
}
+4 -4
View File
@@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660"
integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA=
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
"@types/node@^6.0.46":
version "6.0.78"
+5 -3
View File
@@ -7,7 +7,9 @@
"engines": {
"vscode": "^1.5.0"
},
"extensionKind": "ui",
"extensionKind": [
"ui"
],
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"enableProposedApi": true,
"categories": [
@@ -23,6 +25,6 @@
"watch": "gulp watch-extension:git-ui"
},
"devDependencies": {
"@types/node": "^10.14.8"
"@types/node": "^12.11.7"
}
}
}
+2 -2
View File
@@ -41,12 +41,12 @@ export function exec(command: string, options: cp.ExecOptions & { stdin?: string
(error ? reject : resolve)({ error, stdout, stderr });
});
if (options.stdin) {
child.stdin.write(options.stdin, (err: any) => {
child.stdin!.write(options.stdin, (err: any) => {
if (err) {
reject(err);
return;
}
child.stdin.end((err: any) => {
child.stdin!.end((err: any) => {
if (err) {
reject(err);
}
+4 -4
View File
@@ -2,7 +2,7 @@
# yarn lockfile v1
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
+190 -16
View File
@@ -109,6 +109,24 @@
"dark": "resources/icons/dark/stage.svg"
}
},
{
"command": "git.stageAllTracked",
"title": "%command.stageAllTracked%",
"category": "Git",
"icon": {
"light": "resources/icons/light/stage.svg",
"dark": "resources/icons/dark/stage.svg"
}
},
{
"command": "git.stageAllUntracked",
"title": "%command.stageAllUntracked%",
"category": "Git",
"icon": {
"light": "resources/icons/light/stage.svg",
"dark": "resources/icons/dark/stage.svg"
}
},
{
"command": "git.stageSelectedRanges",
"title": "%command.stageSelectedRanges%",
@@ -178,6 +196,24 @@
"dark": "resources/icons/dark/clean.svg"
}
},
{
"command": "git.cleanAllTracked",
"title": "%command.cleanAllTracked%",
"category": "Git",
"icon": {
"light": "resources/icons/light/clean.svg",
"dark": "resources/icons/dark/clean.svg"
}
},
{
"command": "git.cleanAllUntracked",
"title": "%command.cleanAllUntracked%",
"category": "Git",
"icon": {
"light": "resources/icons/light/clean.svg",
"dark": "resources/icons/dark/clean.svg"
}
},
{
"command": "git.commit",
"title": "%command.commit%",
@@ -267,6 +303,11 @@
"title": "%command.createTag%",
"category": "Git"
},
{
"command": "git.deleteTag",
"title": "%command.deleteTag%",
"category": "Git"
},
{
"command": "git.fetch",
"title": "%command.fetch%",
@@ -396,6 +437,11 @@
"command": "git.stashApplyLatest",
"title": "%command.stashApplyLatest%",
"category": "Git"
},
{
"command": "git.stashDrop",
"title": "%command.stashDrop%",
"category": "Git"
}
],
"menus": {
@@ -440,6 +486,14 @@
"command": "git.stageAll",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageAllTracked",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageAllUntracked",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageSelectedRanges",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
@@ -564,6 +618,10 @@
"command": "git.createTag",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.deleteTag",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.fetch",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
@@ -651,6 +709,10 @@
{
"command": "git.stashApplyLatest",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stashDrop",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
}
],
"scm/title": [
@@ -804,6 +866,11 @@
"group": "6_stash",
"when": "scmProvider == git"
},
{
"command": "git.stashDrop",
"group": "6_stash",
"when": "scmProvider == git"
},
{
"command": "git.showOutput",
"group": "7_repository",
@@ -840,22 +907,62 @@
},
{
"command": "git.cleanAll",
"when": "scmProvider == git && scmResourceGroup == workingTree",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges == mixed",
"group": "1_modification"
},
{
"command": "git.stageAll",
"when": "scmProvider == git && scmResourceGroup == workingTree",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges == mixed",
"group": "1_modification"
},
{
"command": "git.cleanAll",
"when": "scmProvider == git && scmResourceGroup == workingTree",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges == mixed",
"group": "inline"
},
{
"command": "git.stageAll",
"when": "scmProvider == git && scmResourceGroup == workingTree",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges == mixed",
"group": "inline"
},
{
"command": "git.cleanAllTracked",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges != mixed",
"group": "1_modification"
},
{
"command": "git.stageAllTracked",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges != mixed",
"group": "1_modification"
},
{
"command": "git.cleanAllTracked",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges != mixed",
"group": "inline"
},
{
"command": "git.stageAllTracked",
"when": "scmProvider == git && scmResourceGroup == workingTree && config.git.untrackedChanges != mixed",
"group": "inline"
},
{
"command": "git.cleanAllUntracked",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "1_modification"
},
{
"command": "git.stageAllUntracked",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "1_modification"
},
{
"command": "git.cleanAllUntracked",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "inline"
},
{
"command": "git.stageAllUntracked",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "inline"
}
],
@@ -1031,13 +1138,63 @@
"command": "git.revealInExplorer",
"when": "scmProvider == git && scmResourceGroup == workingTree",
"group": "2_view"
},
{
"command": "git.openChange",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "navigation"
},
{
"command": "git.openHEADFile",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "navigation"
},
{
"command": "git.openFile",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "navigation"
},
{
"command": "git.stage",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "1_modification"
},
{
"command": "git.clean",
"when": "scmProvider == git && scmResourceGroup == untracked && !gitFreshRepository",
"group": "1_modification"
},
{
"command": "git.clean",
"when": "scmProvider == git && scmResourceGroup == untracked && !gitFreshRepository",
"group": "inline"
},
{
"command": "git.stage",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "inline"
},
{
"command": "git.openFile2",
"when": "scmProvider == git && scmResourceGroup == untracked && config.git.showInlineOpenFileAction && config.git.openDiffOnClick",
"group": "inline0"
},
{
"command": "git.openChange",
"when": "scmProvider == git && scmResourceGroup == untracked && config.git.showInlineOpenFileAction && !config.git.openDiffOnClick",
"group": "inline0"
},
{
"command": "git.ignore",
"when": "scmProvider == git && scmResourceGroup == untracked",
"group": "1_modification@3"
}
],
"editor/title": [
{
"command": "git.openFile",
"group": "navigation",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
},
{
"command": "git.openChange",
@@ -1047,44 +1204,44 @@
{
"command": "git.stageSelectedRanges",
"group": "2_git@1",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
},
{
"command": "git.unstageSelectedRanges",
"group": "2_git@2",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
},
{
"command": "git.revertSelectedRanges",
"group": "2_git@3",
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
}
],
"editor/context": [
{
"command": "git.stageSelectedRanges",
"group": "2_git@1",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
},
{
"command": "git.unstageSelectedRanges",
"group": "2_git@2",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
},
{
"command": "git.revertSelectedRanges",
"group": "2_git@3",
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
}
],
"scm/change/title": [
{
"command": "git.stageChange",
"when": "originalResourceScheme == git"
"when": "originalResourceScheme == gitfs"
},
{
"command": "git.revertChange",
"when": "originalResourceScheme == git"
"when": "originalResourceScheme == gitfs"
}
]
},
@@ -1174,7 +1331,8 @@
"%config.countBadge.off%"
],
"description": "%config.countBadge%",
"default": "all"
"default": "all",
"scope": "resource"
},
"git.checkoutType": {
"type": "string",
@@ -1434,6 +1592,22 @@
],
"default": "committerdate",
"description": "%config.branchSortOrder%"
},
"git.untrackedChanges": {
"type": "string",
"enum": [
"mixed",
"separate",
"hidden"
],
"enumDescriptions": [
"%config.untrackedChanges.mixed%",
"%config.untrackedChanges.separate%",
"%config.untrackedChanges.hidden%"
],
"default": "mixed",
"description": "%config.untrackedChanges%",
"scope": "resource"
}
}
},
@@ -1585,7 +1759,7 @@
"byline": "^5.0.0",
"file-type": "^7.2.0",
"iconv-lite": "^0.4.24",
"jschardet": "^1.6.0",
"jschardet": "2.1.1",
"vscode-extension-telemetry": "0.1.1",
"vscode-nls": "^4.0.0",
"vscode-uri": "^2.0.0",
@@ -1595,7 +1769,7 @@
"@types/byline": "4.2.31",
"@types/file-type": "^5.2.1",
"@types/mocha": "2.2.43",
"@types/node": "^10.14.8",
"@types/node": "^12.11.7",
"@types/which": "^1.0.28",
"mocha": "^3.2.0"
}
+12 -2
View File
@@ -11,6 +11,8 @@
"command.openHEADFile": "Open File (HEAD)",
"command.stage": "Stage Changes",
"command.stageAll": "Stage All Changes",
"command.stageAllTracked": "Stage All Tracked Changes",
"command.stageAllUntracked": "Stage All Untracked Changes",
"command.stageSelectedRanges": "Stage Selected Ranges",
"command.revertSelectedRanges": "Revert Selected Ranges",
"command.stageChange": "Stage Change",
@@ -20,6 +22,8 @@
"command.unstageSelectedRanges": "Unstage Selected Ranges",
"command.clean": "Discard Changes",
"command.cleanAll": "Discard All Changes",
"command.cleanAllTracked": "Discard All Tracked Changes",
"command.cleanAllUntracked": "Discard All Untracked Changes",
"command.commit": "Commit",
"command.commitStaged": "Commit Staged",
"command.commitEmpty": "Commit Empty",
@@ -37,6 +41,7 @@
"command.renameBranch": "Rename Branch...",
"command.merge": "Merge Branch...",
"command.createTag": "Create Tag",
"command.deleteTag": "Delete Tag",
"command.fetch": "Fetch",
"command.fetchPrune": "Fetch (Prune)",
"command.fetchAll": "Fetch From All Remotes",
@@ -56,13 +61,14 @@
"command.publish": "Publish Branch...",
"command.showOutput": "Show Git Output",
"command.ignore": "Add to .gitignore",
"command.revealInExplorer": "Reveal in Explorer",
"command.revealInExplorer": "Reveal in Side Bar",
"command.stashIncludeUntracked": "Stash (Include Untracked)",
"command.stash": "Stash",
"command.stashPop": "Pop Stash...",
"command.stashPopLatest": "Pop Latest Stash",
"command.stashApply": "Apply Stash...",
"command.stashApplyLatest": "Apply Latest Stash",
"command.stashDrop": "Drop Stash...",
"config.enabled": "Whether git is enabled.",
"config.path": "Path and filename of the git executable, e.g. `C:\\Program Files\\Git\\bin\\git.exe` (Windows).",
"config.autoRepositoryDetection": "Configures when repositories should be automatically detected.",
@@ -119,7 +125,7 @@
"config.scanRepositories": "List of paths to search for git repositories in.",
"config.showProgress": "Controls whether git actions should show progress.",
"config.rebaseWhenSync": "Force git to use rebase when running the sync command.",
"config.confirmEmptyCommits": "Always confirm the creation of empty commits.",
"config.confirmEmptyCommits": "Always confirm the creation of empty commits for the 'Git: Commit Empty' command.",
"config.fetchOnPull": "Fetch all branches when pulling or just the current one.",
"config.pullTags": "Fetch all tags when pulling.",
"config.autoStash": "Stash any changes before pulling and restore them after successful pull.",
@@ -129,6 +135,10 @@
"config.openDiffOnClick": "Controls whether the diff editor should be opened when clicking a change. Otherwise the regular editor will be opened.",
"config.supportCancellation": "Controls whether a notification comes up when running the Sync action, which allows the user to cancel the operation.",
"config.branchSortOrder": "Controls the sort order for branches.",
"config.untrackedChanges": "Controls how untracked changes behave.",
"config.untrackedChanges.mixed": "All changes, tracked and untracked, appear together and behave equally.",
"config.untrackedChanges.separate": "Untracked changes appear separately in the Source Control view. They are also excluded from several actions.",
"config.untrackedChanges.hidden": "Untracked changes are hidden and excluded from several actions.",
"colors.added": "Color for added resources.",
"colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.",
+5
View File
@@ -8,6 +8,7 @@ import { Repository as BaseRepository, Resource } from '../repository';
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState } from './git';
import { Event, SourceControlInputBox, Uri, SourceControl } from 'vscode';
import { mapEvent } from '../util';
import { toGitUri } from '../uri';
class ApiInputBox implements InputBox {
set value(value: string) { this._inputBox.value = value; }
@@ -234,5 +235,9 @@ export class ApiImpl implements API {
return this._model.repositories.map(r => new ApiRepository(r));
}
toGitUri(uri: Uri, ref: string): Uri {
return toGitUri(uri, ref);
}
constructor(private _model: Model) { }
}
+2
View File
@@ -185,6 +185,8 @@ export interface API {
readonly repositories: Repository[];
readonly onDidOpenRepository: Event<Repository>;
readonly onDidCloseRepository: Event<Repository>;
toGitUri(uri: Uri, ref: string): Uri;
}
export interface GitExtension {
+6 -36
View File
@@ -3,9 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as http from 'http';
import * as fs from 'fs';
import * as nls from 'vscode-nls';
import { IPCClient } from './ipc/ipcClient';
const localize = nls.loadMessageBundle();
@@ -20,10 +20,6 @@ function main(argv: string[]): void {
return fatal('Wrong number of arguments');
}
if (!process.env['VSCODE_GIT_ASKPASS_HANDLE']) {
return fatal('Missing handle');
}
if (!process.env['VSCODE_GIT_ASKPASS_PIPE']) {
return fatal('Missing pipe');
}
@@ -33,40 +29,14 @@ function main(argv: string[]): void {
}
const output = process.env['VSCODE_GIT_ASKPASS_PIPE'] as string;
const socketPath = process.env['VSCODE_GIT_ASKPASS_HANDLE'] as string;
const request = argv[2];
const host = argv[4].substring(1, argv[4].length - 2);
const opts: http.RequestOptions = {
socketPath,
path: '/',
method: 'POST'
};
const ipcClient = new IPCClient('askpass');
const req = http.request(opts, res => {
if (res.statusCode !== 200) {
return fatal(`Bad status code: ${res.statusCode}`);
}
const chunks: string[] = [];
res.setEncoding('utf8');
res.on('data', (d: string) => chunks.push(d));
res.on('end', () => {
const raw = chunks.join('');
try {
const result = JSON.parse(raw);
fs.writeFileSync(output, result + '\n');
} catch (err) {
return fatal(`Error parsing response`);
}
setTimeout(() => process.exit(0), 0);
});
});
req.on('error', () => fatal('Error in request'));
req.write(JSON.stringify({ request, host }));
req.end();
ipcClient.call({ request, host }).then(res => {
fs.writeFileSync(output, res + '\n');
setTimeout(() => process.exit(0), 0);
}).catch(err => fatal(err));
}
main(process.argv);
+18 -81
View File
@@ -3,15 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable, window, InputBoxOptions } from 'vscode';
import { denodeify } from './util';
import { window, InputBoxOptions } from 'vscode';
import { IDisposable } from './util';
import * as path from 'path';
import * as http from 'http';
import * as os from 'os';
import * as fs from 'fs';
import * as crypto from 'crypto';
const randomBytes = denodeify<Buffer>(crypto.randomBytes);
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
export interface AskpassEnvironment {
GIT_ASKPASS: string;
@@ -21,68 +16,21 @@ export interface AskpassEnvironment {
VSCODE_GIT_ASKPASS_HANDLE?: string;
}
function getIPCHandlePath(nonce: string): string {
if (process.platform === 'win32') {
return `\\\\.\\pipe\\vscode-git-askpass-${nonce}-sock`;
export class Askpass implements IIPCHandler {
private disposable: IDisposable;
static getDisabledEnv(): AskpassEnvironment {
return {
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
};
}
if (process.env['XDG_RUNTIME_DIR']) {
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-askpass-${nonce}.sock`);
constructor(ipc: IIPCServer) {
this.disposable = ipc.registerHandler('askpass', this);
}
return path.join(os.tmpdir(), `vscode-git-askpass-${nonce}.sock`);
}
export class Askpass implements Disposable {
private server: http.Server;
private ipcHandlePathPromise: Promise<string>;
private ipcHandlePath: string | undefined;
private enabled = true;
constructor() {
this.server = http.createServer((req, res) => this.onRequest(req, res));
this.ipcHandlePathPromise = this.setup().catch(err => {
console.error(err);
return '';
});
}
private async setup(): Promise<string> {
const buffer = await randomBytes(20);
const nonce = buffer.toString('hex');
const ipcHandlePath = getIPCHandlePath(nonce);
this.ipcHandlePath = ipcHandlePath;
try {
this.server.listen(ipcHandlePath);
this.server.on('error', err => console.error(err));
} catch (err) {
console.error('Could not launch git askpass helper.');
this.enabled = false;
}
return ipcHandlePath;
}
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
const chunks: string[] = [];
req.setEncoding('utf8');
req.on('data', (d: string) => chunks.push(d));
req.on('end', () => {
const { request, host } = JSON.parse(chunks.join(''));
this.prompt(host, request).then(result => {
res.writeHead(200);
res.end(JSON.stringify(result));
}, () => {
res.writeHead(500);
res.end();
});
});
}
private async prompt(host: string, request: string): Promise<string> {
async handle({ request, host }: { request: string, host: string }): Promise<string> {
const options: InputBoxOptions = {
password: /password/i.test(request),
placeHolder: request,
@@ -93,27 +41,16 @@ export class Askpass implements Disposable {
return await window.showInputBox(options) || '';
}
async getEnv(): Promise<AskpassEnvironment> {
if (!this.enabled) {
return {
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
};
}
getEnv(): AskpassEnvironment {
return {
ELECTRON_RUN_AS_NODE: '1',
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
VSCODE_GIT_ASKPASS_NODE: process.execPath,
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js'),
VSCODE_GIT_ASKPASS_HANDLE: await this.ipcHandlePathPromise
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js')
};
}
dispose(): void {
this.server.close();
if (this.ipcHandlePath && process.platform !== 'win32') {
fs.unlinkSync(this.ipcHandlePath);
}
this.disposable.dispose();
}
}
}
+210 -139
View File
@@ -3,19 +3,19 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Uri, commands, Disposable, window, workspace, QuickPickItem, OutputChannel, Range, WorkspaceEdit, Position, LineChange, SourceControlResourceState, TextDocumentShowOptions, ViewColumn, ProgressLocation, TextEditor, MessageOptions, WorkspaceFolder } from 'vscode';
import { Git, CommitOptions, Stash, ForcePushMode } from './git';
import { Repository, Resource, ResourceGroupType } from './repository';
import { Model } from './model';
import { toGitUri, fromGitUri } from './uri';
import { grep, isDescendant, pathEquals } from './util';
import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange, getModifiedRange } from './staging';
import * as path from 'path';
import { lstat, Stats } from 'fs';
import * as os from 'os';
import * as path from 'path';
import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder } from 'vscode';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as nls from 'vscode-nls';
import { Ref, RefType, Branch, GitErrorCodes, Status } from './api/git';
import { Branch, GitErrorCodes, Ref, RefType, Status } from './api/git';
import { CommitOptions, ForcePushMode, Git, Stash } from './git';
import { Model } from './model';
import { Repository, Resource, ResourceGroupType } from './repository';
import { applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineChange, toLineRanges } from './staging';
import { fromGitUri, toGitUri, isGitUri } from './uri';
import { grep, isDescendant, pathEquals } from './util';
const localize = nls.loadMessageBundle();
@@ -99,7 +99,7 @@ class CreateBranchItem implements QuickPickItem {
constructor(private cc: CommandCenter) { }
get label(): string { return localize('create branch', '$(plus) Create new branch...'); }
get label(): string { return '$(plus) ' + localize('create branch', 'Create new branch...'); }
get description(): string { return ''; }
get alwaysShow(): boolean { return true; }
@@ -113,7 +113,7 @@ class CreateBranchFromItem implements QuickPickItem {
constructor(private cc: CommandCenter) { }
get label(): string { return localize('create branch from', '$(plus) Create new branch from...'); }
get label(): string { return '$(plus) ' + localize('create branch from', 'Create new branch from...'); }
get description(): string { return ''; }
get alwaysShow(): boolean { return true; }
@@ -136,7 +136,7 @@ class AddRemoteItem implements QuickPickItem {
constructor(private cc: CommandCenter) { }
get label(): string { return localize('add remote', '$(plus) Add a new remote...'); }
get label(): string { return '$(plus) ' + localize('add remote', 'Add a new remote...'); }
get description(): string { return ''; }
get alwaysShow(): boolean { return true; }
@@ -170,14 +170,14 @@ function command(commandId: string, options: CommandOptions = {}): Function {
};
}
const ImageMimetypes = [
'image/png',
'image/gif',
'image/jpeg',
'image/webp',
'image/tiff',
'image/bmp'
];
// const ImageMimetypes = [
// 'image/png',
// 'image/gif',
// 'image/jpeg',
// 'image/webp',
// 'image/tiff',
// 'image/bmp'
// ];
async function categorizeResourceByResolution(resources: Resource[]): Promise<{ merge: Resource[], resolved: Resource[], unresolved: Resource[], deletionConflicts: Resource[] }> {
const selection = resources.filter(s => s instanceof Resource) as Resource[];
@@ -213,6 +213,12 @@ function createCheckoutItems(repository: Repository): CheckoutItem[] {
return [...heads, ...tags, ...remoteHeads];
}
class TagItem implements QuickPickItem {
get label(): string { return this.ref.name ?? ''; }
get description(): string { return this.ref.commit?.substr(0, 8) ?? ''; }
constructor(readonly ref: Ref) { }
}
enum PushType {
Push,
PushTo,
@@ -289,10 +295,10 @@ export class CommandCenter {
}
} else {
if (resource.type !== Status.DELETED_BY_THEM) {
left = await this.getLeftResource(resource);
left = this.getLeftResource(resource);
}
right = await this.getRightResource(resource);
right = this.getRightResource(resource);
}
const title = this.getTitle(resource);
@@ -324,79 +330,40 @@ export class CommandCenter {
}
}
private async getURI(uri: Uri, ref: string): Promise<Uri | undefined> {
const repository = this.model.getRepository(uri);
if (!repository) {
return toGitUri(uri, ref);
}
try {
let gitRef = ref;
if (gitRef === '~') {
const uriString = uri.toString();
const [indexStatus] = repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
gitRef = indexStatus ? '' : 'HEAD';
}
const { size, object } = await repository.getObjectDetails(gitRef, uri.fsPath);
const { mimetype } = await repository.detectObjectType(object);
if (mimetype === 'text/plain') {
return toGitUri(uri, ref);
}
if (size > 1000000) { // 1 MB
return Uri.parse(`data:;label:${path.basename(uri.fsPath)};description:${gitRef},`);
}
if (ImageMimetypes.indexOf(mimetype) > -1) {
const contents = await repository.buffer(gitRef, uri.fsPath);
return Uri.parse(`data:${mimetype};label:${path.basename(uri.fsPath)};description:${gitRef};size:${size};base64,${contents.toString('base64')}`);
}
return Uri.parse(`data:;label:${path.basename(uri.fsPath)};description:${gitRef},`);
} catch (err) {
return toGitUri(uri, ref);
}
}
private async getLeftResource(resource: Resource): Promise<Uri | undefined> {
private getLeftResource(resource: Resource): Uri | undefined {
switch (resource.type) {
case Status.INDEX_MODIFIED:
case Status.INDEX_RENAMED:
case Status.INDEX_ADDED:
return this.getURI(resource.original, 'HEAD');
return toGitUri(resource.original, 'HEAD');
case Status.MODIFIED:
case Status.UNTRACKED:
return this.getURI(resource.resourceUri, '~');
return toGitUri(resource.resourceUri, '~');
case Status.DELETED_BY_THEM:
return this.getURI(resource.resourceUri, '');
return toGitUri(resource.resourceUri, '');
}
return undefined;
}
private async getRightResource(resource: Resource): Promise<Uri | undefined> {
private getRightResource(resource: Resource): Uri | undefined {
switch (resource.type) {
case Status.INDEX_MODIFIED:
case Status.INDEX_ADDED:
case Status.INDEX_COPIED:
case Status.INDEX_RENAMED:
return this.getURI(resource.resourceUri, '');
return toGitUri(resource.resourceUri, '');
case Status.INDEX_DELETED:
case Status.DELETED:
return this.getURI(resource.resourceUri, 'HEAD');
return toGitUri(resource.resourceUri, 'HEAD');
case Status.DELETED_BY_US:
return this.getURI(resource.resourceUri, '~3');
return toGitUri(resource.resourceUri, '~3');
case Status.DELETED_BY_THEM:
return this.getURI(resource.resourceUri, '~2');
return toGitUri(resource.resourceUri, '~2');
case Status.MODIFIED:
case Status.UNTRACKED:
@@ -453,7 +420,7 @@ export class CommandCenter {
}
@command('git.clone')
async clone(url?: string): Promise<void> {
async clone(url?: string, parentPath?: string): Promise<void> {
if (!url) {
url = await window.showInputBox({
prompt: localize('repourl', "Repository URL"),
@@ -473,31 +440,33 @@ export class CommandCenter {
url = url.trim().replace(/^git\s+clone\s+/, '');
const config = workspace.getConfiguration('git');
let defaultCloneDirectory = config.get<string>('defaultCloneDirectory') || os.homedir();
defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir());
if (!parentPath) {
const config = workspace.getConfiguration('git');
let defaultCloneDirectory = config.get<string>('defaultCloneDirectory') || os.homedir();
defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir());
const uris = await window.showOpenDialog({
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri: Uri.file(defaultCloneDirectory),
openLabel: localize('selectFolder', "Select Repository Location")
});
const uris = await window.showOpenDialog({
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri: Uri.file(defaultCloneDirectory),
openLabel: localize('selectFolder', "Select Repository Location")
});
if (!uris || uris.length === 0) {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_directory' });
return;
if (!uris || uris.length === 0) {
/* __GDPR__
"clone" : {
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_directory' });
return;
}
const uri = uris[0];
parentPath = uri.fsPath;
}
const uri = uris[0];
const parentPath = uri.fsPath;
try {
const opts = {
location: ProgressLocation.Notification,
@@ -507,7 +476,7 @@ export class CommandCenter {
const repositoryPath = await window.withProgress(
opts,
(progress, token) => this.git.clone(url!, parentPath, progress, token)
(progress, token) => this.git.clone(url!, parentPath!, progress, token)
);
let message = localize('proposeopen', "Would you like to open the cloned repository?");
@@ -686,7 +655,7 @@ export class CommandCenter {
let uris: Uri[] | undefined;
if (arg instanceof Uri) {
if (arg.scheme === 'git') {
if (isGitUri(arg)) {
uris = [Uri.file(fromGitUri(arg).path)];
} else if (arg.scheme === 'file') {
uris = [arg];
@@ -765,7 +734,7 @@ export class CommandCenter {
return;
}
const HEAD = await this.getLeftResource(resource);
const HEAD = this.getLeftResource(resource);
const basename = path.basename(resource.resourceUri.fsPath);
const title = `${basename} (HEAD)`;
@@ -866,7 +835,8 @@ export class CommandCenter {
}
const workingTree = selection.filter(s => s.resourceGroupType === ResourceGroupType.WorkingTree);
const scmResources = [...workingTree, ...resolved, ...unresolved];
const untracked = selection.filter(s => s.resourceGroupType === ResourceGroupType.Untracked);
const scmResources = [...workingTree, ...untracked, ...resolved, ...unresolved];
this.outputChannel.appendLine(`git.stage.scmResources ${scmResources.length}`);
if (!scmResources.length) {
@@ -907,7 +877,9 @@ export class CommandCenter {
}
}
await repository.add([]);
const config = workspace.getConfiguration('git', Uri.file(repository.root));
const untrackedChanges = config.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges');
await repository.add([], untrackedChanges === 'mixed' ? undefined : { update: true });
}
private async _stageDeletionConflict(repository: Repository, uri: Uri): Promise<void> {
@@ -945,6 +917,24 @@ export class CommandCenter {
}
}
@command('git.stageAllTracked', { repository: true })
async stageAllTracked(repository: Repository): Promise<void> {
const resources = repository.workingTreeGroup.resourceStates
.filter(r => r.type !== Status.UNTRACKED && r.type !== Status.IGNORED);
const uris = resources.map(r => r.resourceUri);
await repository.add(uris);
}
@command('git.stageAllUntracked', { repository: true })
async stageAllUntracked(repository: Repository): Promise<void> {
const resources = [...repository.workingTreeGroup.resourceStates, ...repository.untrackedGroup.resourceStates]
.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED);
const uris = resources.map(r => r.resourceUri);
await repository.add(uris);
}
@command('git.stageChange')
async stageChange(uri: Uri, changes: LineChange[], index: number): Promise<void> {
const textEditor = window.visibleTextEditors.filter(e => e.document.uri.toString() === uri.toString())[0];
@@ -1090,7 +1080,7 @@ export class CommandCenter {
const modifiedDocument = textEditor.document;
const modifiedUri = modifiedDocument.uri;
if (modifiedUri.scheme !== 'git') {
if (!isGitUri(modifiedUri)) {
return;
}
@@ -1131,8 +1121,8 @@ export class CommandCenter {
resourceStates = [resource];
}
const scmResources = resourceStates
.filter(s => s instanceof Resource && s.resourceGroupType === ResourceGroupType.WorkingTree) as Resource[];
const scmResources = resourceStates.filter(s => s instanceof Resource
&& (s.resourceGroupType === ResourceGroupType.WorkingTree || s.resourceGroupType === ResourceGroupType.Untracked)) as Resource[];
if (!scmResources.length) {
return;
@@ -1189,41 +1179,11 @@ export class CommandCenter {
const untrackedResources = resources.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED);
if (untrackedResources.length === 0) {
const message = resources.length === 1
? localize('confirm discard all single', "Are you sure you want to discard changes in {0}?", path.basename(resources[0].resourceUri.fsPath))
: localize('confirm discard all', "Are you sure you want to discard ALL changes in {0} files?\nThis is IRREVERSIBLE!\nYour current working set will be FOREVER LOST.", resources.length);
const yes = resources.length === 1
? localize('discardAll multiple', "Discard 1 File")
: localize('discardAll', "Discard All {0} Files", resources.length);
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick !== yes) {
return;
}
await repository.clean(resources.map(r => r.resourceUri));
return;
await this._cleanTrackedChanges(repository, resources);
} else if (resources.length === 1) {
const message = localize('confirm delete', "Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST.", path.basename(resources[0].resourceUri.fsPath));
const yes = localize('delete file', "Delete file");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick !== yes) {
return;
}
await repository.clean(resources.map(r => r.resourceUri));
await this._cleanUntrackedChange(repository, resources[0]);
} else if (trackedResources.length === 0) {
const message = localize('confirm delete multiple', "Are you sure you want to DELETE {0} files?", resources.length);
const yes = localize('delete files', "Delete Files");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick !== yes) {
return;
}
await repository.clean(resources.map(r => r.resourceUri));
await this._cleanUntrackedChanges(repository, resources);
} else { // resources.length > 1 && untrackedResources.length > 0 && trackedResources.length > 0
const untrackedMessage = untrackedResources.length === 1
? localize('there are untracked files single', "The following untracked file will be DELETED FROM DISK if discarded: {0}.", path.basename(untrackedResources[0].resourceUri.fsPath))
@@ -1248,6 +1208,74 @@ export class CommandCenter {
}
}
@command('git.cleanAllTracked', { repository: true })
async cleanAllTracked(repository: Repository): Promise<void> {
const resources = repository.workingTreeGroup.resourceStates
.filter(r => r.type !== Status.UNTRACKED && r.type !== Status.IGNORED);
if (resources.length === 0) {
return;
}
await this._cleanTrackedChanges(repository, resources);
}
@command('git.cleanAllUntracked', { repository: true })
async cleanAllUntracked(repository: Repository): Promise<void> {
const resources = [...repository.workingTreeGroup.resourceStates, ...repository.untrackedGroup.resourceStates]
.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED);
if (resources.length === 0) {
return;
}
if (resources.length === 1) {
await this._cleanUntrackedChange(repository, resources[0]);
} else {
await this._cleanUntrackedChanges(repository, resources);
}
}
private async _cleanTrackedChanges(repository: Repository, resources: Resource[]): Promise<void> {
const message = resources.length === 1
? localize('confirm discard all single', "Are you sure you want to discard changes in {0}?", path.basename(resources[0].resourceUri.fsPath))
: localize('confirm discard all', "Are you sure you want to discard ALL changes in {0} files?\nThis is IRREVERSIBLE!\nYour current working set will be FOREVER LOST.", resources.length);
const yes = resources.length === 1
? localize('discardAll multiple', "Discard 1 File")
: localize('discardAll', "Discard All {0} Files", resources.length);
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick !== yes) {
return;
}
await repository.clean(resources.map(r => r.resourceUri));
}
private async _cleanUntrackedChange(repository: Repository, resource: Resource): Promise<void> {
const message = localize('confirm delete', "Are you sure you want to DELETE {0}?\nThis is IRREVERSIBLE!\nThis file will be FOREVER LOST.", path.basename(resource.resourceUri.fsPath));
const yes = localize('delete file', "Delete file");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick !== yes) {
return;
}
await repository.clean([resource.resourceUri]);
}
private async _cleanUntrackedChanges(repository: Repository, resources: Resource[]): Promise<void> {
const message = localize('confirm delete multiple', "Are you sure you want to DELETE {0} files?", resources.length);
const yes = localize('delete files', "Delete Files");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
if (pick !== yes) {
return;
}
await repository.clean(resources.map(r => r.resourceUri));
}
private async smartCommit(
repository: Repository,
getCommitMessage: () => Promise<string | undefined>,
@@ -1271,7 +1299,7 @@ export class CommandCenter {
if (promptToSaveFilesBeforeCommit === 'staged' || repository.indexGroup.resourceStates.length > 0) {
documents = documents
.filter(d => repository.indexGroup.resourceStates.some(s => s.resourceUri.path === d.uri.fsPath));
.filter(d => repository.indexGroup.resourceStates.some(s => pathEquals(s.resourceUri.fsPath, d.uri.fsPath)));
}
if (documents.length > 0) {
@@ -1356,6 +1384,10 @@ export class CommandCenter {
opts.all = 'tracked';
}
if (opts.all && config.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges') !== 'mixed') {
opts.all = 'tracked';
}
await repository.commit(message, opts);
const postCommitCommand = config.get<'none' | 'push' | 'sync'>('postCommitCommand');
@@ -1376,6 +1408,7 @@ export class CommandCenter {
const message = repository.inputBox.value;
const getCommitMessage = async () => {
let _message: string | undefined = message;
if (!_message) {
let value: string | undefined = undefined;
@@ -1400,7 +1433,7 @@ export class CommandCenter {
});
}
return _message ? repository.cleanUpCommitEditMessage(_message) : _message;
return _message;
};
const didCommit = await this.smartCommit(repository, getCommitMessage, opts);
@@ -1485,7 +1518,7 @@ export class CommandCenter {
if (commit.parents.length > 1) {
const yes = localize('undo commit', "Undo merge commit");
const result = await window.showWarningMessage(localize('merge commit', "The last commit was a merge commit. Are you sure you want to undo it?"), yes);
const result = await window.showWarningMessage(localize('merge commit', "The last commit was a merge commit. Are you sure you want to undo it?"), { modal: true }, yes);
if (result !== yes) {
return;
@@ -1705,6 +1738,26 @@ export class CommandCenter {
await repository.tag(name, message);
}
@command('git.deleteTag', { repository: true })
async deleteTag(repository: Repository): Promise<void> {
const picks = repository.refs.filter(ref => ref.type === RefType.Tag)
.map(ref => new TagItem(ref));
if (picks.length === 0) {
window.showWarningMessage(localize('no tags', "This repository has no tags."));
return;
}
const placeHolder = localize('select a tag to delete', 'Select a tag to delete');
const choice = await window.showQuickPick(picks, { placeHolder });
if (!choice) {
return;
}
await repository.deleteTag(choice.label);
}
@command('git.fetch', { repository: true })
async fetch(repository: Repository): Promise<void> {
if (repository.remotes.length === 0) {
@@ -2073,9 +2126,14 @@ export class CommandCenter {
return;
}
const branchName = repository.HEAD && repository.HEAD.name || '';
if (remotes.length === 1) {
return await repository.pushTo(remotes[0].name, branchName, true);
}
const addRemote = new AddRemoteItem(this);
const picks = [...repository.remotes.map(r => ({ label: r.name, description: r.pushUrl })), addRemote];
const branchName = repository.HEAD && repository.HEAD.name || '';
const placeHolder = localize('pick remote', "Pick a remote to publish the branch '{0}' to:", branchName);
const choice = await window.showQuickPick(picks, { placeHolder });
@@ -2133,7 +2191,8 @@ export class CommandCenter {
}
private async _stash(repository: Repository, includeUntracked = false): Promise<void> {
const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0;
const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0
&& (!includeUntracked || repository.untrackedGroup.resourceStates.length === 0);
const noStagedChanges = repository.indexGroup.resourceStates.length === 0;
if (noUnstagedChanges && noStagedChanges) {
@@ -2215,6 +2274,18 @@ export class CommandCenter {
await repository.applyStash();
}
@command('git.stashDrop', { repository: true })
async stashDrop(repository: Repository): Promise<void> {
const placeHolder = localize('pick stash to drop', "Pick a stash to drop");
const stash = await this.pickStash(repository, placeHolder);
if (!stash) {
return;
}
await repository.dropStash(stash.index);
}
private async pickStash(repository: Repository, placeHolder: string): Promise<Stash | undefined> {
const stashes = await repository.getStashes();
@@ -2352,7 +2423,7 @@ export class CommandCenter {
return undefined;
}
if (uri.scheme === 'git') {
if (isGitUri(uri)) {
const { path } = fromGitUri(uri);
uri = Uri.file(path);
}
+1 -1
View File
@@ -147,4 +147,4 @@ export class GitContentProvider {
dispose(): void {
this.disposables.forEach(d => d.dispose());
}
}
}
+1
View File
@@ -113,6 +113,7 @@ class GitDecorationProvider implements DecorationProvider {
this.collectSubmoduleDecorationData(newDecorations);
this.collectDecorationData(this.repository.indexGroup, newDecorations);
this.collectDecorationData(this.repository.untrackedGroup, newDecorations);
this.collectDecorationData(this.repository.workingTreeGroup, newDecorations);
this.collectDecorationData(this.repository.mergeGroup, newDecorations);
-2
View File
@@ -5,8 +5,6 @@
import * as jschardet from 'jschardet';
jschardet.Constants.MINIMUM_THRESHOLD = 0.2;
function detectEncodingByBOM(buffer: Buffer): string | null {
if (!buffer || buffer.length < 2) {
return null;
+199
View File
@@ -0,0 +1,199 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { workspace, Uri, Disposable, Event, EventEmitter, window, FileSystemProvider, FileChangeEvent, FileStat, FileType, FileChangeType, FileSystemError } from 'vscode';
import { debounce, throttle } from './decorators';
import { fromGitUri, toGitUri } from './uri';
import { Model, ModelChangeEvent, OriginalResourceChangeEvent } from './model';
import { filterEvent, eventToPromise, isDescendant, pathEquals, EmptyDisposable } from './util';
interface CacheRow {
uri: Uri;
timestamp: number;
}
const THREE_MINUTES = 1000 * 60 * 3;
const FIVE_MINUTES = 1000 * 60 * 5;
export class GitFileSystemProvider implements FileSystemProvider {
private _onDidChangeFile = new EventEmitter<FileChangeEvent[]>();
readonly onDidChangeFile: Event<FileChangeEvent[]> = this._onDidChangeFile.event;
private changedRepositoryRoots = new Set<string>();
private cache = new Map<string, CacheRow>();
private mtime = new Date().getTime();
private disposables: Disposable[] = [];
constructor(private model: Model) {
this.disposables.push(
model.onDidChangeRepository(this.onDidChangeRepository, this),
model.onDidChangeOriginalResource(this.onDidChangeOriginalResource, this),
workspace.registerFileSystemProvider('gitfs', this, { isReadonly: true, isCaseSensitive: true }),
workspace.registerResourceLabelFormatter({
scheme: 'gitfs',
formatting: {
label: '${path} (git)',
separator: '/'
}
})
);
setInterval(() => this.cleanup(), FIVE_MINUTES);
}
private onDidChangeRepository({ repository }: ModelChangeEvent): void {
this.changedRepositoryRoots.add(repository.root);
this.eventuallyFireChangeEvents();
}
private onDidChangeOriginalResource({ uri }: OriginalResourceChangeEvent): void {
if (uri.scheme !== 'file') {
return;
}
const gitUri = toGitUri(uri, '', { replaceFileExtension: true });
this.mtime = new Date().getTime();
this._onDidChangeFile.fire([{ type: FileChangeType.Changed, uri: gitUri }]);
}
@debounce(1100)
private eventuallyFireChangeEvents(): void {
this.fireChangeEvents();
}
@throttle
private async fireChangeEvents(): Promise<void> {
if (!window.state.focused) {
const onDidFocusWindow = filterEvent(window.onDidChangeWindowState, e => e.focused);
await eventToPromise(onDidFocusWindow);
}
const events: FileChangeEvent[] = [];
for (const { uri } of this.cache.values()) {
const fsPath = uri.fsPath;
for (const root of this.changedRepositoryRoots) {
if (isDescendant(root, fsPath)) {
events.push({ type: FileChangeType.Changed, uri });
break;
}
}
}
if (events.length > 0) {
this.mtime = new Date().getTime();
this._onDidChangeFile.fire(events);
}
this.changedRepositoryRoots.clear();
}
private cleanup(): void {
const now = new Date().getTime();
const cache = new Map<string, CacheRow>();
for (const row of this.cache.values()) {
const { path } = fromGitUri(row.uri);
const isOpen = workspace.textDocuments
.filter(d => d.uri.scheme === 'file')
.some(d => pathEquals(d.uri.fsPath, path));
if (isOpen || now - row.timestamp < THREE_MINUTES) {
cache.set(row.uri.toString(), row);
} else {
// TODO: should fire delete events?
}
}
this.cache = cache;
}
watch(): Disposable {
return EmptyDisposable;
}
stat(uri: Uri): FileStat {
const { submoduleOf } = fromGitUri(uri);
const repository = submoduleOf ? this.model.getRepository(submoduleOf) : this.model.getRepository(uri);
if (!repository) {
throw FileSystemError.FileNotFound();
}
return { type: FileType.File, size: 0, mtime: this.mtime, ctime: 0 };
}
readDirectory(): Thenable<[string, FileType][]> {
throw new Error('Method not implemented.');
}
createDirectory(): void {
throw new Error('Method not implemented.');
}
async readFile(uri: Uri): Promise<Uint8Array> {
let { path, ref, submoduleOf } = fromGitUri(uri);
if (submoduleOf) {
const repository = this.model.getRepository(submoduleOf);
if (!repository) {
throw FileSystemError.FileNotFound();
}
const encoder = new TextEncoder();
if (ref === 'index') {
return encoder.encode(await repository.diffIndexWithHEAD(path));
} else {
return encoder.encode(await repository.diffWithHEAD(path));
}
}
const repository = this.model.getRepository(uri);
if (!repository) {
throw FileSystemError.FileNotFound();
}
const timestamp = new Date().getTime();
const cacheValue: CacheRow = { uri, timestamp };
this.cache.set(uri.toString(), cacheValue);
if (ref === '~') {
const fileUri = Uri.file(path);
const uriString = fileUri.toString();
const [indexStatus] = repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
ref = indexStatus ? '' : 'HEAD';
} else if (/^~\d$/.test(ref)) {
ref = `:${ref[1]}`;
}
try {
return await repository.buffer(ref, path);
} catch (err) {
return new Uint8Array(0);
}
}
writeFile(): void {
throw new Error('Method not implemented.');
}
delete(): void {
throw new Error('Method not implemented.');
}
rename(): void {
throw new Error('Method not implemented.');
}
dispose(): void {
this.disposables.forEach(d => d.dispose());
}
}
+50 -29
View File
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import { promises as fs, exists } from 'fs';
import * as path from 'path';
import * as os from 'os';
import * as cp from 'child_process';
@@ -11,7 +11,7 @@ import * as which from 'which';
import { EventEmitter } from 'events';
import iconv = require('iconv-lite');
import * as filetype from 'file-type';
import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
import { CancellationToken, Progress } from 'vscode';
import { URI } from 'vscode-uri';
import { detectEncoding } from './encoding';
@@ -22,8 +22,6 @@ import { StringDecoder } from 'string_decoder';
// https://github.com/microsoft/vscode/issues/65693
const MAX_CLI_LENGTH = 30000;
const readfile = denodeify<string, string | null, string>(fs.readFile);
export interface IGit {
path: string;
version: string;
@@ -196,13 +194,13 @@ async function exec(child: cp.ChildProcess, cancellationToken?: CancellationToke
}),
new Promise<Buffer>(c => {
const buffers: Buffer[] = [];
on(child.stdout, 'data', (b: Buffer) => buffers.push(b));
once(child.stdout, 'close', () => c(Buffer.concat(buffers)));
on(child.stdout!, 'data', (b: Buffer) => buffers.push(b));
once(child.stdout!, 'close', () => c(Buffer.concat(buffers)));
}),
new Promise<string>(c => {
const buffers: Buffer[] = [];
on(child.stderr, 'data', (b: Buffer) => buffers.push(b));
once(child.stderr, 'close', () => c(Buffer.concat(buffers).toString('utf8')));
on(child.stderr!, 'data', (b: Buffer) => buffers.push(b));
once(child.stderr!, 'close', () => c(Buffer.concat(buffers).toString('utf8')));
})
]) as Promise<[number, Buffer, string]>;
@@ -350,7 +348,7 @@ export class Git {
let folderPath = path.join(parentPath, folderName);
let count = 1;
while (count < 20 && await new Promise(c => fs.exists(folderPath, c))) {
while (count < 20 && await new Promise(c => exists(folderPath, c))) {
folderName = `${baseFolderName}-${count++}`;
folderPath = path.join(parentPath, folderName);
}
@@ -360,7 +358,7 @@ export class Git {
const onSpawn = (child: cp.ChildProcess) => {
const decoder = new StringDecoder('utf8');
const lineStream = new byline.LineStream({ encoding: 'utf8' });
child.stderr.on('data', (buffer: Buffer) => lineStream.write(decoder.write(buffer)));
child.stderr!.on('data', (buffer: Buffer) => lineStream.write(decoder.write(buffer)));
let totalProgress = 0;
let previousProgress = 0;
@@ -438,7 +436,7 @@ export class Git {
}
if (options.input) {
child.stdin.end(options.input, 'utf8');
child.stdin!.end(options.input, 'utf8');
}
const bufferResult = await exec(child, options.cancellationToken);
@@ -763,9 +761,10 @@ export class Repository {
async log(options?: LogOptions): Promise<Commit[]> {
const maxEntries = options && typeof options.maxEntries === 'number' && options.maxEntries > 0 ? options.maxEntries : 32;
const args = ['log', '-' + maxEntries, `--pretty=format:${COMMIT_FORMAT}%x00%x00`];
const gitResult = await this.run(args);
if (gitResult.exitCode) {
// An empty repo.
// An empty repo
return [];
}
@@ -882,7 +881,7 @@ export class Repository {
async detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> {
const child = await this.stream(['show', object]);
const buffer = await readBytes(child.stdout, 4100);
const buffer = await readBytes(child.stdout!, 4100);
try {
child.kill();
@@ -1151,7 +1150,7 @@ export class Repository {
async stage(path: string, data: string): Promise<void> {
const child = this.stream(['hash-object', '--stdin', '-w', '--path', path], { stdio: [null, null, null] });
child.stdin.end(data, 'utf8');
child.stdin!.end(data, 'utf8');
const { exitCode, stdout } = await exec(child);
const hash = stdout.toString('utf8');
@@ -1163,11 +1162,12 @@ export class Repository {
});
}
const treeish = await this.getCommit('HEAD').then(() => 'HEAD', () => '');
let mode: string;
let add: string = '';
try {
const details = await this.getObjectDetails('HEAD', path);
const details = await this.getObjectDetails(treeish, path);
mode = details.mode;
} catch (err) {
if (err.gitErrorCode !== GitErrorCodes.UnknownPath) {
@@ -1327,6 +1327,11 @@ export class Repository {
await this.run(args);
}
async deleteTag(name: string): Promise<void> {
let args = ['tag', '-d', name];
await this.run(args);
}
async clean(paths: string[]): Promise<void> {
const pathsByGroup = groupBy(paths, p => path.dirname(p));
const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]);
@@ -1592,6 +1597,24 @@ export class Repository {
}
}
async dropStash(index?: number): Promise<void> {
const args = ['stash', 'drop'];
if (typeof index === 'number') {
args.push(`stash@{${index}}`);
}
try {
await this.run(args);
} catch (err) {
if (/No stash found/.test(err.stderr || '')) {
err.gitErrorCode = GitErrorCodes.NoStashFound;
}
throw err;
}
}
getStatus(limit = 5000): Promise<{ status: IFileStatus[]; didHitLimit: boolean; }> {
return new Promise<{ status: IFileStatus[]; didHitLimit: boolean; }>((c, e) => {
const parser = new GitStatusParser();
@@ -1618,19 +1641,19 @@ export class Repository {
if (parser.status.length > limit) {
child.removeListener('exit', onExit);
child.stdout.removeListener('data', onStdoutData);
child.stdout!.removeListener('data', onStdoutData);
child.kill();
c({ status: parser.status.slice(0, limit), didHitLimit: true });
}
};
child.stdout.setEncoding('utf8');
child.stdout.on('data', onStdoutData);
child.stdout!.setEncoding('utf8');
child.stdout!.on('data', onStdoutData);
const stderrData: string[] = [];
child.stderr.setEncoding('utf8');
child.stderr.on('data', raw => stderrData.push(raw as string));
child.stderr!.setEncoding('utf8');
child.stderr!.on('data', raw => stderrData.push(raw as string));
child.on('error', cpErrorHandler(e));
child.on('exit', onExit);
@@ -1789,18 +1812,17 @@ export class Repository {
}
}
cleanupCommitEditMessage(message: string): string {
//TODO: Support core.commentChar
// TODO: Support core.commentChar
stripCommitMessageComments(message: string): string {
return message.replace(/^\s*#.*$\n?/gm, '').trim();
}
async getMergeMessage(): Promise<string | undefined> {
const mergeMsgPath = path.join(this.repositoryRoot, '.git', 'MERGE_MSG');
try {
const raw = await readfile(mergeMsgPath, 'utf8');
return raw.trim();
const raw = await fs.readFile(mergeMsgPath, 'utf8');
return this.stripCommitMessageComments(raw);
} catch {
return undefined;
}
@@ -1823,9 +1845,8 @@ export class Repository {
templatePath = path.join(this.repositoryRoot, templatePath);
}
const raw = await readfile(templatePath, 'utf8');
return raw.trim();
const raw = await fs.readFile(templatePath, 'utf8');
return this.stripCommitMessageComments(raw);
} catch (err) {
return '';
}
@@ -1848,7 +1869,7 @@ export class Repository {
const gitmodulesPath = path.join(this.root, '.gitmodules');
try {
const gitmodulesRaw = await readfile(gitmodulesPath, 'utf8');
const gitmodulesRaw = await fs.readFile(gitmodulesPath, 'utf8');
return parseGitmodules(gitmodulesRaw);
} catch (err) {
if (/ENOENT/.test(err.message)) {
+45
View File
@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as http from 'http';
export class IPCClient {
private ipcHandlePath: string;
constructor(private handlerName: string) {
const ipcHandlePath = process.env['VSCODE_GIT_IPC_HANDLE'];
if (!ipcHandlePath) {
throw new Error('Missing VSCODE_GIT_IPC_HANDLE');
}
this.ipcHandlePath = ipcHandlePath;
}
call(request: any): Promise<any> {
const opts: http.RequestOptions = {
socketPath: this.ipcHandlePath,
path: `/${this.handlerName}`,
method: 'POST'
};
return new Promise((c, e) => {
const req = http.request(opts, res => {
if (res.statusCode !== 200) {
return e(new Error(`Bad status code: ${res.statusCode}`));
}
const chunks: Buffer[] = [];
res.on('data', d => chunks.push(d));
res.on('end', () => c(JSON.parse(Buffer.concat(chunks).toString('utf8'))));
});
req.on('error', err => e(err));
req.write(JSON.stringify(request));
req.end();
});
}
}
+106
View File
@@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vscode';
import { toDisposable } from '../util';
import * as path from 'path';
import * as http from 'http';
import * as os from 'os';
import * as fs from 'fs';
import * as crypto from 'crypto';
function getIPCHandlePath(nonce: string): string {
if (process.platform === 'win32') {
return `\\\\.\\pipe\\vscode-git-ipc-${nonce}-sock`;
}
if (process.env['XDG_RUNTIME_DIR']) {
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-ipc-${nonce}.sock`);
}
return path.join(os.tmpdir(), `vscode-git-ipc-${nonce}.sock`);
}
export interface IIPCHandler {
handle(request: any): Promise<any>;
}
export async function createIPCServer(): Promise<IIPCServer> {
const server = http.createServer();
const buffer = await new Promise<Buffer>((c, e) => crypto.randomBytes(20, (err, buf) => err ? e(err) : c(buf)));
const nonce = buffer.toString('hex');
const ipcHandlePath = getIPCHandlePath(nonce);
return new Promise((c, e) => {
try {
server.on('error', err => e(err));
server.listen(ipcHandlePath);
c(new IPCServer(server, ipcHandlePath));
} catch (err) {
e(err);
}
});
}
export interface IIPCServer extends Disposable {
readonly ipcHandlePath: string | undefined;
getEnv(): any;
registerHandler(name: string, handler: IIPCHandler): Disposable;
}
class IPCServer implements IIPCServer, Disposable {
private handlers = new Map<string, IIPCHandler>();
get ipcHandlePath(): string { return this._ipcHandlePath; }
constructor(private server: http.Server, private _ipcHandlePath: string) {
this.server.on('request', this.onRequest.bind(this));
}
registerHandler(name: string, handler: IIPCHandler): Disposable {
this.handlers.set(`/${name}`, handler);
return toDisposable(() => this.handlers.delete(name));
}
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
if (!req.url) {
console.warn(`Request lacks url`);
return;
}
const handler = this.handlers.get(req.url);
if (!handler) {
console.warn(`IPC handler for ${req.url} not found`);
return;
}
const chunks: Buffer[] = [];
req.on('data', d => chunks.push(d));
req.on('end', () => {
const request = JSON.parse(Buffer.concat(chunks).toString('utf8'));
handler.handle(request).then(result => {
res.writeHead(200);
res.end(JSON.stringify(result));
}, () => {
res.writeHead(500);
res.end();
});
});
}
getEnv(): any {
return { VSCODE_GIT_IPC_HANDLE: this.ipcHandlePath };
}
dispose(): void {
this.handlers.clear();
this.server.close();
if (this._ipcHandlePath && process.platform !== 'win32') {
fs.unlinkSync(this._ipcHandlePath);
}
}
}
+23 -5
View File
@@ -11,6 +11,7 @@ import { findGit, Git, IGit } from './git';
import { Model } from './model';
import { CommandCenter } from './commands';
import { GitContentProvider } from './contentProvider';
import { GitFileSystemProvider } from './fileSystemProvider';
import { GitDecorations } from './decorationProvider';
import { Askpass } from './askpass';
import { toDisposable, filterEvent, eventToPromise } from './util';
@@ -18,9 +19,9 @@ import TelemetryReporter from 'vscode-extension-telemetry';
import { GitExtension } from './api/git';
import { GitProtocolHandler } from './protocolHandler';
import { GitExtensionImpl } from './api/extension';
// {{SQL CARBON EDIT}} - remove unused imports
// import * as path from 'path';
// import * as fs from 'fs';
import { createIPCServer, IIPCServer } from './ipc/ipcServer';
const deactivateTasks: { (): Promise<any>; }[] = [];
@@ -33,10 +34,26 @@ export async function deactivate(): Promise<any> {
async function createModel(context: ExtensionContext, outputChannel: OutputChannel, telemetryReporter: TelemetryReporter, disposables: Disposable[]): Promise<Model> {
const pathHint = workspace.getConfiguration('git').get<string>('path');
const info = await findGit(pathHint, path => outputChannel.appendLine(localize('looking', "Looking for git in: {0}", path)));
const askpass = new Askpass();
disposables.push(askpass);
const env = await askpass.getEnv();
let env: any = {};
let ipc: IIPCServer | undefined;
try {
ipc = await createIPCServer();
disposables.push(ipc);
env = { ...env, ...ipc.getEnv() };
} catch {
// noop
}
if (ipc) {
const askpass = new Askpass(ipc);
disposables.push(askpass);
env = { ...env, ...askpass.getEnv() };
} else {
env = { ...env, ...Askpass.getDisabledEnv() };
}
const git = new Git({ gitPath: info.path, version: info.version, env });
const model = new Model(git, context.globalState, outputChannel);
disposables.push(model);
@@ -63,6 +80,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
disposables.push(
new CommandCenter(git, model, outputChannel, telemetryReporter),
new GitContentProvider(model),
new GitFileSystemProvider(model),
new GitDecorations(model),
new GitProtocolHandler()
);
@@ -198,4 +216,4 @@ async function checkGitVersion(_info: IGit): Promise<void> {
// await config.update('ignoreLegacyWarning', true, true);
// }
// {{SQL CARBON EDIT}} - End
}
}
+23 -5
View File
@@ -6,7 +6,7 @@
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel } from 'vscode';
import { Repository, RepositoryState } from './repository';
import { memoize, sequentialize, debounce } from './decorators';
import { dispose, anyEvent, filterEvent, isDescendant, firstIndex } from './util';
import { dispose, anyEvent, filterEvent, isDescendant, firstIndex, pathEquals } from './util';
import { Git } from './git';
import * as path from 'path';
import * as fs from 'fs';
@@ -240,10 +240,7 @@ export class Model {
return;
}
const config = workspace.getConfiguration('git');
const ignoredRepos = new Set(config.get<Array<string>>('ignoredRepositories'));
if (ignoredRepos.has(rawRoot)) {
if (this.shouldRepositoryBeIgnored(rawRoot)) {
return;
}
@@ -261,6 +258,27 @@ export class Model {
}
}
private shouldRepositoryBeIgnored(repositoryRoot: string): boolean {
const config = workspace.getConfiguration('git');
const ignoredRepos = config.get<string[]>('ignoredRepositories') || [];
for (const ignoredRepo of ignoredRepos) {
if (path.isAbsolute(ignoredRepo)) {
if (pathEquals(ignoredRepo, repositoryRoot)) {
return true;
}
} else {
for (const folder of workspace.workspaceFolders || []) {
if (pathEquals(path.join(folder.uri.fsPath, ignoredRepo), repositoryRoot)) {
return true;
}
}
}
}
return false;
}
private open(repository: Repository): void {
this.outputChannel.appendLine(`Open repository: ${repository.root}`);
+76 -29
View File
@@ -3,17 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, Decoration, Memento, SourceControlInputBoxValidationType, OutputChannel, LogLevel, env, ProgressOptions, CancellationToken } from 'vscode';
import { Repository as BaseRepository, Commit, Stash, GitError, Submodule, CommitOptions, ForcePushMode } from './git';
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent, combinedDisposable } from './util';
import { memoize, throttle, debounce } from './decorators';
import { toGitUri } from './uri';
import { AutoFetcher } from './autofetch';
import * as path from 'path';
import * as nls from 'vscode-nls';
import * as fs from 'fs';
import * as path from 'path';
import { CancellationToken, Command, Disposable, env, Event, EventEmitter, LogLevel, Memento, OutputChannel, ProgressLocation, ProgressOptions, scm, SourceControl, SourceControlInputBox, SourceControlInputBoxValidation, SourceControlInputBoxValidationType, SourceControlResourceDecorations, SourceControlResourceGroup, SourceControlResourceState, ThemeColor, Uri, window, workspace, WorkspaceEdit, Decoration } from 'vscode';
import * as nls from 'vscode-nls';
import { Branch, Change, GitErrorCodes, LogOptions, Ref, RefType, Remote, Status } from './api/git';
import { AutoFetcher } from './autofetch';
import { debounce, memoize, throttle } from './decorators';
import { Commit, CommitOptions, ForcePushMode, GitError, Repository as BaseRepository, Stash, Submodule } from './git';
import { StatusBarCommands } from './statusbar';
import { Branch, Ref, Remote, RefType, GitErrorCodes, Status, LogOptions, Change } from './api/git';
import { toGitUri } from './uri';
import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, IDisposable, isDescendant, onceEvent } from './util';
import { IFileWatcher, watch } from './watch';
const timeout = (millis: number) => new Promise(c => setTimeout(c, millis));
@@ -33,7 +33,8 @@ export const enum RepositoryState {
export const enum ResourceGroupType {
Merge,
Index,
WorkingTree
WorkingTree,
Untracked
}
export class Resource implements SourceControlResourceState {
@@ -292,6 +293,7 @@ export const enum Operation {
Merge = 'Merge',
Ignore = 'Ignore',
Tag = 'Tag',
DeleteTag = 'DeleteTag',
Stash = 'Stash',
CheckIgnore = 'CheckIgnore',
GetObjectDetails = 'GetObjectDetails',
@@ -569,6 +571,9 @@ export class Repository implements Disposable {
private _workingTreeGroup: SourceControlResourceGroup;
get workingTreeGroup(): GitResourceGroup { return this._workingTreeGroup as GitResourceGroup; }
private _untrackedGroup: SourceControlResourceGroup;
get untrackedGroup(): GitResourceGroup { return this._untrackedGroup as GitResourceGroup; }
private _HEAD: Branch | undefined;
get HEAD(): Branch | undefined {
return this._HEAD;
@@ -641,6 +646,7 @@ export class Repository implements Disposable {
this.mergeGroup.resourceStates = [];
this.indexGroup.resourceStates = [];
this.workingTreeGroup.resourceStates = [];
this.untrackedGroup.resourceStates = [];
this._sourceControl.count = 0;
}
@@ -708,6 +714,7 @@ export class Repository implements Disposable {
this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "MERGE CHANGES"));
this._indexGroup = this._sourceControl.createResourceGroup('index', localize('staged changes', "STAGED CHANGES"));
this._workingTreeGroup = this._sourceControl.createResourceGroup('workingTree', localize('changes', "CHANGES"));
this._untrackedGroup = this._sourceControl.createResourceGroup('untracked', localize('untracked changes', "UNTRACKED CHANGES"));
const updateIndexGroupVisibility = () => {
const config = workspace.getConfiguration('git', root);
@@ -721,11 +728,16 @@ export class Repository implements Disposable {
const onConfigListenerForBranchSortOrder = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.branchSortOrder', root));
onConfigListenerForBranchSortOrder(this.updateModelState, this, this.disposables);
const onConfigListenerForUntracked = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.untrackedChanges', root));
onConfigListenerForUntracked(this.updateModelState, this, this.disposables);
this.mergeGroup.hideWhenEmpty = true;
this.untrackedGroup.hideWhenEmpty = true;
this.disposables.push(this.mergeGroup);
this.disposables.push(this.indexGroup);
this.disposables.push(this.workingTreeGroup);
this.disposables.push(this.untrackedGroup);
this.disposables.push(new AutoFetcher(this, globalState));
@@ -911,8 +923,8 @@ export class Repository implements Disposable {
return this.run(Operation.HashObject, () => this.repository.hashObject(data));
}
async add(resources: Uri[]): Promise<void> {
await this.run(Operation.Add, () => this.repository.add(resources.map(r => r.fsPath)));
async add(resources: Uri[], opts?: { update?: boolean }): Promise<void> {
await this.run(Operation.Add, () => this.repository.add(resources.map(r => r.fsPath), opts));
}
async rm(resources: Uri[]): Promise<void> {
@@ -957,6 +969,7 @@ export class Repository implements Disposable {
const toClean: string[] = [];
const toCheckout: string[] = [];
const submodulesToUpdate: string[] = [];
const resourceStates = [...this.workingTreeGroup.resourceStates, ...this.untrackedGroup.resourceStates];
resources.forEach(r => {
const fsPath = r.fsPath;
@@ -969,7 +982,7 @@ export class Repository implements Disposable {
}
const raw = r.toString();
const scmResource = find(this.workingTreeGroup.resourceStates, sr => sr.resourceUri.toString() === raw);
const scmResource = find(resourceStates, sr => sr.resourceUri.toString() === raw);
if (!scmResource) {
return;
@@ -1021,6 +1034,10 @@ export class Repository implements Disposable {
await this.run(Operation.Tag, () => this.repository.tag(name, message));
}
async deleteTag(name: string): Promise<void> {
await this.run(Operation.DeleteTag, () => this.repository.deleteTag(name));
}
async checkout(treeish: string): Promise<void> {
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, []));
}
@@ -1249,6 +1266,10 @@ export class Repository implements Disposable {
return await this.run(Operation.Stash, () => this.repository.popStash(index));
}
async dropStash(index?: number): Promise<void> {
return await this.run(Operation.Stash, () => this.repository.dropStash(index));
}
async applyStash(index?: number): Promise<void> {
return await this.run(Operation.Stash, () => this.repository.applyStash(index));
}
@@ -1257,10 +1278,6 @@ export class Repository implements Disposable {
return await this.run(Operation.GetCommitTemplate, async () => this.repository.getCommitTemplate());
}
async cleanUpCommitEditMessage(editMessage: string): Promise<string> {
return this.repository.cleanupCommitEditMessage(editMessage);
}
async ignore(files: Uri[]): Promise<void> {
return await this.run(Operation.Ignore, async () => {
const ignoreFile = `${this.repository.root}${path.sep}.gitignore`;
@@ -1298,7 +1315,7 @@ export class Repository implements Disposable {
// https://git-scm.com/docs/git-check-ignore#git-check-ignore--z
const child = this.repository.stream(['check-ignore', '-v', '-z', '--stdin'], { stdio: [null, null, null] });
child.stdin.end(filePaths.join('\0'), 'utf8');
child.stdin!.end(filePaths.join('\0'), 'utf8');
const onExit = (exitCode: number) => {
if (exitCode === 1) {
@@ -1320,12 +1337,12 @@ export class Repository implements Disposable {
data += raw;
};
child.stdout.setEncoding('utf8');
child.stdout.on('data', onStdoutData);
child.stdout!.setEncoding('utf8');
child.stdout!.on('data', onStdoutData);
let stderr: string = '';
child.stderr.setEncoding('utf8');
child.stderr.on('data', raw => stderr += raw);
child.stderr!.setEncoding('utf8');
child.stderr!.on('data', raw => stderr += raw);
child.on('error', reject);
child.on('exit', onExit);
@@ -1427,6 +1444,7 @@ export class Repository implements Disposable {
private async updateModelState(): Promise<void> {
const { status, didHitLimit } = await this.repository.getStatus();
const config = workspace.getConfiguration('git');
const scopedConfig = workspace.getConfiguration('git', Uri.file(this.repository.root));
const shouldIgnore = config.get<boolean>('ignoreLimitWarning') === true;
const useIcons = !config.get<boolean>('decorations.enabled', true);
this.isRepositoryHuge = didHitLimit;
@@ -1487,17 +1505,29 @@ export class Repository implements Disposable {
this._submodules = submodules!;
this.rebaseCommit = rebaseCommit;
const untrackedChanges = scopedConfig.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges');
const index: Resource[] = [];
const workingTree: Resource[] = [];
const merge: Resource[] = [];
const untracked: Resource[] = [];
status.forEach(raw => {
const uri = Uri.file(path.join(this.repository.root, raw.path));
const renameUri = raw.rename ? Uri.file(path.join(this.repository.root, raw.rename)) : undefined;
const renameUri = raw.rename
? Uri.file(path.join(this.repository.root, raw.rename))
: undefined;
switch (raw.x + raw.y) {
case '??': return workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.UNTRACKED, useIcons));
case '!!': return workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.IGNORED, useIcons));
case '??': switch (untrackedChanges) {
case 'mixed': return workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.UNTRACKED, useIcons));
case 'separate': return untracked.push(new Resource(ResourceGroupType.Untracked, uri, Status.UNTRACKED, useIcons));
default: return undefined;
}
case '!!': switch (untrackedChanges) {
case 'mixed': return workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.IGNORED, useIcons));
case 'separate': return untracked.push(new Resource(ResourceGroupType.Untracked, uri, Status.IGNORED, useIcons));
default: return undefined;
}
case 'DD': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.BOTH_DELETED, useIcons));
case 'AU': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.ADDED_BY_US, useIcons));
case 'UD': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.DELETED_BY_THEM, useIcons));
@@ -1520,6 +1550,7 @@ export class Repository implements Disposable {
case 'D': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.DELETED, useIcons, renameUri)); break;
case 'A': workingTree.push(new Resource(ResourceGroupType.WorkingTree, uri, Status.INTENT_TO_ADD, useIcons, renameUri)); break;
}
return undefined;
});
@@ -1527,6 +1558,7 @@ export class Repository implements Disposable {
this.mergeGroup.resourceStates = merge;
this.indexGroup.resourceStates = index;
this.workingTreeGroup.resourceStates = workingTree;
this.untrackedGroup.resourceStates = untracked;
// set count badge
this.setCountBadge();
@@ -1537,12 +1569,27 @@ export class Repository implements Disposable {
}
private setCountBadge(): void {
const countBadge = workspace.getConfiguration('git').get<string>('countBadge');
let count = this.mergeGroup.resourceStates.length + this.indexGroup.resourceStates.length + this.workingTreeGroup.resourceStates.length;
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
const countBadge = config.get<'all' | 'tracked' | 'off'>('countBadge');
const untrackedChanges = config.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges');
let count =
this.mergeGroup.resourceStates.length +
this.indexGroup.resourceStates.length +
this.workingTreeGroup.resourceStates.length;
switch (countBadge) {
case 'off': count = 0; break;
case 'tracked': count = count - this.workingTreeGroup.resourceStates.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED).length; break;
case 'tracked':
if (untrackedChanges === 'mixed') {
count -= this.workingTreeGroup.resourceStates.filter(r => r.type === Status.UNTRACKED || r.type === Status.IGNORED).length;
}
break;
case 'all':
if (untrackedChanges === 'separate') {
count += this.untrackedGroup.resourceStates.length;
}
break;
}
this._sourceControl.count = count;
@@ -1644,7 +1691,7 @@ export class Repository implements Disposable {
const head = HEAD.name || tagName || (HEAD.commit || '').substr(0, 8);
return head
+ (this.workingTreeGroup.resourceStates.length > 0 ? '*' : '')
+ (this.workingTreeGroup.resourceStates.length + this.untrackedGroup.resourceStates.length > 0 ? '*' : '')
+ (this.indexGroup.resourceStates.length > 0 ? '+' : '')
+ (this.mergeGroup.resourceStates.length > 0 ? '!' : '');
}
-11
View File
@@ -1,11 +0,0 @@
declare module 'jschardet' {
export interface IDetectedMap {
encoding: string,
confidence: number
}
export function detect(buffer: Buffer): IDetectedMap;
export const Constants: {
MINIMUM_THRESHOLD: number,
}
}
+23 -4
View File
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Uri } from 'vscode';
import * as qs from 'querystring';
export interface GitUriParams {
path: string;
@@ -11,8 +12,26 @@ export interface GitUriParams {
submoduleOf?: string;
}
export function isGitUri(uri: Uri): boolean {
return /^git(fs)?$/.test(uri.scheme);
}
export function fromGitUri(uri: Uri): GitUriParams {
return JSON.parse(uri.query);
const result = qs.parse(uri.query) as any;
if (!result) {
throw new Error('Invalid git URI: empty query');
}
if (typeof result.path !== 'string') {
throw new Error('Invalid git URI: missing path');
}
if (typeof result.ref !== 'string') {
throw new Error('Invalid git URI: missing ref');
}
return result;
}
export interface GitUriOptions {
@@ -42,8 +61,8 @@ export function toGitUri(uri: Uri, ref: string, options: GitUriOptions = {}): Ur
}
return uri.with({
scheme: 'git',
scheme: 'gitfs',
path,
query: JSON.stringify(params)
query: qs.stringify(params as any)
});
}
}
+4 -15
View File
@@ -6,7 +6,7 @@
import { Event } from 'vscode';
import { dirname, sep } from 'path';
import { Readable } from 'stream';
import * as fs from 'fs';
import { promises as fs, createReadStream } from 'fs';
import * as byline from 'byline';
export function log(...args: any[]): void {
@@ -140,25 +140,14 @@ export function groupBy<T>(arr: T[], fn: (el: T) => string): { [key: string]: T[
}, Object.create(null));
}
export function denodeify<A, B, C, R>(fn: Function): (a: A, b: B, c: C) => Promise<R>;
export function denodeify<A, B, R>(fn: Function): (a: A, b: B) => Promise<R>;
export function denodeify<A, R>(fn: Function): (a: A) => Promise<R>;
export function denodeify<R>(fn: Function): (...args: any[]) => Promise<R>;
export function denodeify<R>(fn: Function): (...args: any[]) => Promise<R> {
return (...args) => new Promise<R>((c, e) => fn(...args, (err: any, r: any) => err ? e(err) : c(r)));
}
export function nfcall<R>(fn: Function, ...args: any[]): Promise<R> {
return new Promise<R>((c, e) => fn(...args, (err: any, r: any) => err ? e(err) : c(r)));
}
export async function mkdirp(path: string, mode?: number): Promise<boolean> {
const mkdir = async () => {
try {
await nfcall(fs.mkdir, path, mode);
await fs.mkdir(path, mode);
} catch (err) {
if (err.code === 'EEXIST') {
const stat = await nfcall<fs.Stats>(fs.stat, path);
const stat = await fs.stat(path);
if (stat.isDirectory()) {
return;
@@ -232,7 +221,7 @@ export function find<T>(array: T[], fn: (t: T) => boolean): T | undefined {
export async function grep(filename: string, pattern: RegExp): Promise<boolean> {
return new Promise<boolean>((c, e) => {
const fileStream = fs.createReadStream(filename, { encoding: 'utf8' });
const fileStream = createReadStream(filename, { encoding: 'utf8' });
const stream = byline(fileStream);
stream.on('data', (line: string) => {
if (pattern.test(line)) {
+8 -8
View File
@@ -26,10 +26,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb"
integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ==
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
"@types/which@^1.0.28":
version "1.0.28"
@@ -176,10 +176,10 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
jschardet@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.6.0.tgz#c7d1a71edcff2839db2f9ec30fc5d5ebd3c1a678"
integrity sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==
jschardet@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184"
integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q==
json3@3.3.2:
version "3.3.2"
+1
View File
@@ -21,6 +21,7 @@ body img {
.container {
padding: 5px 0 0 10px;
box-sizing: border-box;
-webkit-user-select: none;
user-select: none;
}
+25 -18
View File
@@ -70,7 +70,8 @@
let ctrlPressed = false;
let altPressed = false;
let hasLoadedImage = false;
let consumeClick = false;
let consumeClick = true;
let isActive = false;
// Elements
const container = document.body;
@@ -117,10 +118,16 @@
});
}
function changeActive(value) {
function setActive(value) {
isActive = value;
if (value) {
container.classList.add('zoom-in');
consumeClick = true;
if (isMac ? altPressed : ctrlPressed) {
container.classList.remove('zoom-in');
container.classList.add('zoom-out');
} else {
container.classList.remove('zoom-out');
container.classList.add('zoom-in');
}
} else {
ctrlPressed = false;
altPressed = false;
@@ -202,7 +209,10 @@
return;
}
consumeClick = false;
ctrlPressed = e.ctrlKey;
altPressed = e.altKey;
consumeClick = !isActive;
});
container.addEventListener('click', (/** @type {MouseEvent} */ e) => {
@@ -214,14 +224,6 @@
return;
}
ctrlPressed = e.ctrlKey;
altPressed = e.altKey;
if (isMac ? altPressed : ctrlPressed) {
container.classList.remove('zoom-in');
container.classList.add('zoom-out');
}
if (consumeClick) {
consumeClick = false;
return;
@@ -239,6 +241,11 @@
});
container.addEventListener('wheel', (/** @type {WheelEvent} */ e) => {
// Prevent pinch to zoom
if (e.ctrlKey) {
e.preventDefault();
}
if (!image || !hasLoadedImage) {
return;
}
@@ -254,9 +261,9 @@
let delta = e.deltaY > 0 ? 1 : -1;
updateScale(scale * (1 - delta * SCALE_PINCH_FACTOR));
});
}, { passive: false });
window.addEventListener('scroll', () => {
window.addEventListener('scroll', e => {
if (!image || !hasLoadedImage || !image.parentElement || scale === 'fit') {
return;
}
@@ -265,7 +272,7 @@
if (entry) {
vscode.setState({ scale: entry.scale, offsetX: window.scrollX, offsetY: window.scrollY });
}
});
}, { passive: true });
container.classList.add('image');
@@ -296,7 +303,7 @@
document.body.classList.remove('loading');
});
image.src = decodeURI(settings.src);
image.src = settings.src;
window.addEventListener('message', e => {
switch (e.data.type) {
@@ -305,7 +312,7 @@
break;
case 'setActive':
changeActive(e.data.value);
setActive(e.data.value);
break;
case 'zoomIn':
+1 -2
View File
@@ -29,8 +29,7 @@
"priority": "builtin",
"selector": [
{
"filenamePattern": "*.{jpg,jpe,jpeg,png,bmp,gif,ico,tga,webp}",
"mime": "image/*"
"filenamePattern": "*.{jpg,jpe,jpeg,png,bmp,gif,ico,webp}"
}
]
}
@@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { PreviewStatusBarEntry } from './ownedStatusBarEntry';
const localize = nls.loadMessageBundle();
class BinarySize {
static readonly KB = 1024;
static readonly MB = BinarySize.KB * BinarySize.KB;
static readonly GB = BinarySize.MB * BinarySize.KB;
static readonly TB = BinarySize.GB * BinarySize.KB;
static formatSize(size: number): string {
if (size < BinarySize.KB) {
return localize('sizeB', "{0}B", size);
}
if (size < BinarySize.MB) {
return localize('sizeKB', "{0}KB", (size / BinarySize.KB).toFixed(2));
}
if (size < BinarySize.GB) {
return localize('sizeMB', "{0}MB", (size / BinarySize.MB).toFixed(2));
}
if (size < BinarySize.TB) {
return localize('sizeGB', "{0}GB", (size / BinarySize.GB).toFixed(2));
}
return localize('sizeTB', "{0}TB", (size / BinarySize.TB).toFixed(2));
}
}
export class BinarySizeStatusBarEntry extends PreviewStatusBarEntry {
constructor() {
super({
id: 'imagePreview.binarySize',
name: localize('sizeStatusBar.name', "Image Binary Size"),
alignment: vscode.StatusBarAlignment.Right,
priority: 100,
});
}
public show(owner: string, size: number | undefined) {
if (typeof size === 'number') {
super.showItem(owner, BinarySize.formatSize(size));
} else {
this.hide(owner);
}
}
}
+6 -8
View File
@@ -6,6 +6,7 @@
import * as vscode from 'vscode';
import { PreviewManager } from './preview';
import { SizeStatusBarEntry } from './sizeStatusBarEntry';
import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry';
import { ZoomStatusBarEntry } from './zoomStatusBarEntry';
export function activate(context: vscode.ExtensionContext) {
@@ -14,18 +15,15 @@ export function activate(context: vscode.ExtensionContext) {
const sizeStatusBarEntry = new SizeStatusBarEntry();
context.subscriptions.push(sizeStatusBarEntry);
const binarySizeStatusBarEntry = new BinarySizeStatusBarEntry();
context.subscriptions.push(binarySizeStatusBarEntry);
const zoomStatusBarEntry = new ZoomStatusBarEntry();
context.subscriptions.push(zoomStatusBarEntry);
const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, zoomStatusBarEntry);
const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry);
context.subscriptions.push(vscode.window.registerWebviewEditorProvider(
PreviewManager.viewType,
{
async resolveWebviewEditor(resource: vscode.Uri, editor: vscode.WebviewEditor): Promise<void> {
previewManager.resolve(resource, editor);
}
}));
context.subscriptions.push(vscode.window.registerWebviewEditorProvider(PreviewManager.viewType, previewManager));
context.subscriptions.push(vscode.commands.registerCommand('imagePreview.zoomIn', () => {
previewManager.activePreview?.zoomIn();
@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { Disposable } from './dispose';
export abstract class PreviewStatusBarEntry extends Disposable {
private _showOwner: string | undefined;
protected readonly entry: vscode.StatusBarItem;
constructor(options: vscode.window.StatusBarItemOptions) {
super();
this.entry = this._register(vscode.window.createStatusBarItem(options));
}
protected showItem(owner: string, text: string) {
this._showOwner = owner;
this.entry.text = text;
this.entry.show();
}
public hide(owner: string) {
if (owner === this._showOwner) {
this.entry.hide();
this._showOwner = undefined;
}
}
}
+36 -15
View File
@@ -8,11 +8,12 @@ import * as nls from 'vscode-nls';
import { Disposable } from './dispose';
import { SizeStatusBarEntry } from './sizeStatusBarEntry';
import { Scale, ZoomStatusBarEntry } from './zoomStatusBarEntry';
import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry';
const localize = nls.loadMessageBundle();
export class PreviewManager {
export class PreviewManager implements vscode.WebviewEditorProvider {
public static readonly viewType = 'imagePreview.previewEditor';
@@ -22,14 +23,15 @@ export class PreviewManager {
constructor(
private readonly extensionRoot: vscode.Uri,
private readonly sizeStatusBarEntry: SizeStatusBarEntry,
private readonly binarySizeStatusBarEntry: BinarySizeStatusBarEntry,
private readonly zoomStatusBarEntry: ZoomStatusBarEntry,
) { }
public resolve(
resource: vscode.Uri,
webviewEditor: vscode.WebviewEditor,
) {
const preview = new Preview(this.extensionRoot, resource, webviewEditor, this.sizeStatusBarEntry, this.zoomStatusBarEntry);
public async resolveWebviewEditor(
input: { readonly resource: vscode.Uri, },
webviewEditor: vscode.WebviewPanel,
): Promise<vscode.WebviewEditorCapabilities> {
const preview = new Preview(this.extensionRoot, input.resource, webviewEditor, this.sizeStatusBarEntry, this.binarySizeStatusBarEntry, this.zoomStatusBarEntry);
this._previews.add(preview);
this.setActivePreview(preview);
@@ -42,6 +44,8 @@ export class PreviewManager {
this.setActivePreview(undefined);
}
});
return {};
}
public get activePreview() { return this._activePreview; }
@@ -68,13 +72,15 @@ class Preview extends Disposable {
private _previewState = PreviewState.Visible;
private _imageSize: string | undefined;
private _imageBinarySize: number | undefined;
private _imageZoom: Scale | undefined;
constructor(
private readonly extensionRoot: vscode.Uri,
private readonly resource: vscode.Uri,
private readonly webviewEditor: vscode.WebviewEditor,
private readonly webviewEditor: vscode.WebviewPanel,
private readonly sizeStatusBarEntry: SizeStatusBarEntry,
private readonly binarySizeStatusBarEntry: BinarySizeStatusBarEntry,
private readonly zoomStatusBarEntry: ZoomStatusBarEntry,
) {
super();
@@ -115,11 +121,13 @@ class Preview extends Disposable {
this._register(webviewEditor.onDidChangeViewState(() => {
this.update();
this.webviewEditor.webview.postMessage({ type: 'setActive', value: this.webviewEditor.active });
}));
this._register(webviewEditor.onDidDispose(() => {
if (this._previewState === PreviewState.Active) {
this.sizeStatusBarEntry.hide(this.id);
this.binarySizeStatusBarEntry.hide(this.id);
this.zoomStatusBarEntry.hide(this.id);
}
this._previewState = PreviewState.Disposed;
@@ -137,8 +145,14 @@ class Preview extends Disposable {
}
}));
vscode.workspace.fs.stat(resource).then(({ size }) => {
this._imageBinarySize = size;
this.update();
});
this.render();
this.update();
this.webviewEditor.webview.postMessage({ type: 'setActive', value: this.webviewEditor.active });
}
public zoomIn() {
@@ -167,15 +181,16 @@ class Preview extends Disposable {
if (this.webviewEditor.active) {
this._previewState = PreviewState.Active;
this.sizeStatusBarEntry.show(this.id, this._imageSize || '');
this.binarySizeStatusBarEntry.show(this.id, this._imageBinarySize);
this.zoomStatusBarEntry.show(this.id, this._imageZoom || 'fit');
} else {
if (this._previewState === PreviewState.Active) {
this.sizeStatusBarEntry.hide(this.id);
this.binarySizeStatusBarEntry.hide(this.id);
this.zoomStatusBarEntry.hide(this.id);
}
this._previewState = PreviewState.Visible;
}
this.webviewEditor.webview.postMessage({ type: 'setActive', value: this.webviewEditor.active });
}
private getWebiewContents(): string {
@@ -191,8 +206,11 @@ class Preview extends Disposable {
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- Disable pinch zooming -->
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<title>Image Preview</title>
<link rel="stylesheet" href="${escapeAttribute(this.extensionResource('/media/main.css'))}" type="text/css" media="screen" nonce="${nonce}">
@@ -208,18 +226,21 @@ class Preview extends Disposable {
</html>`;
}
private getResourcePath(webviewEditor: vscode.WebviewEditor, resource: vscode.Uri, version: string) {
private getResourcePath(webviewEditor: vscode.WebviewPanel, resource: vscode.Uri, version: string) {
switch (resource.scheme) {
case 'data':
return encodeURI(resource.toString(true));
return resource.toString(true);
case 'git':
// Show blank image
return encodeURI('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAEElEQVR42gEFAPr/AP///wAI/AL+Sr4t6gAAAABJRU5ErkJggg==');
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAEElEQVR42gEFAPr/AP///wAI/AL+Sr4t6gAAAABJRU5ErkJggg==';
default:
return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString(true) + `?version=${version}`);
// Avoid adding cache busting if there is already a query string
if (resource.query) {
return webviewEditor.webview.asWebviewUri(resource).toString(true);
}
return webviewEditor.webview.asWebviewUri(resource).with({ query: `version=${version}` }).toString(true);
}
}
@@ -4,36 +4,23 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { Disposable } from './dispose';
import * as nls from 'vscode-nls';
import { PreviewStatusBarEntry } from './ownedStatusBarEntry';
const localize = nls.loadMessageBundle();
export class SizeStatusBarEntry extends Disposable {
private readonly _entry: vscode.StatusBarItem;
private _showingOwner: string | undefined;
export class SizeStatusBarEntry extends PreviewStatusBarEntry {
constructor() {
super();
this._entry = this._register(vscode.window.createStatusBarItem({
super({
id: 'imagePreview.size',
name: localize('sizeStatusBar.name', "Image Size"),
alignment: vscode.StatusBarAlignment.Right,
priority: 101 /* to the left of editor status (100) */,
}));
});
}
public show(owner: string, text: string) {
this._showingOwner = owner;
this._entry.text = text;
this._entry.show();
}
public hide(owner: string) {
if (owner === this._showingOwner) {
this._entry.hide();
this._showingOwner = undefined;
}
this.showItem(owner, text);
}
}
@@ -5,7 +5,7 @@
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { Disposable } from './dispose';
import { PreviewStatusBarEntry as OwnedStatusBarEntry } from './ownedStatusBarEntry';
const localize = nls.loadMessageBundle();
@@ -13,22 +13,18 @@ const selectZoomLevelCommandId = '_imagePreview.selectZoomLevel';
export type Scale = number | 'fit';
export class ZoomStatusBarEntry extends Disposable {
private readonly _entry: vscode.StatusBarItem;
export class ZoomStatusBarEntry extends OwnedStatusBarEntry {
private readonly _onDidChangeScale = this._register(new vscode.EventEmitter<{ scale: Scale }>());
public readonly onDidChangeScale = this._onDidChangeScale.event;
private _showOwner: string | undefined;
constructor() {
super();
this._entry = this._register(vscode.window.createStatusBarItem({
super({
id: 'imagePreview.zoom',
name: localize('zoomStatusBar.name', "Image Zoom"),
alignment: vscode.StatusBarAlignment.Right,
priority: 102 /* to the left of editor size entry (101) */,
}));
});
this._register(vscode.commands.registerCommand(selectZoomLevelCommandId, async () => {
type MyPickItem = vscode.QuickPickItem & { scale: Scale };
@@ -47,20 +43,11 @@ export class ZoomStatusBarEntry extends Disposable {
}
}));
this._entry.command = selectZoomLevelCommandId;
this.entry.command = selectZoomLevelCommandId;
}
public show(owner: string, scale: Scale) {
this._showOwner = owner;
this._entry.text = this.zoomLabel(scale);
this._entry.show();
}
public hide(owner: string) {
if (owner === this._showOwner) {
this._entry.hide();
this._showOwner = undefined;
}
this.showItem(owner, this.zoomLabel(scale));
}
private zoomLabel(scale: Scale): string {
+1 -1
View File
@@ -71,7 +71,7 @@
"vscode-nls": "^3.2.1"
},
"devDependencies": {
"@types/node": "10"
"@types/node": "^12.11.7"
},
"__metadata": {
"id": "23",
+4 -4
View File
@@ -2,10 +2,10 @@
# yarn lockfile v1
"@types/node@10":
version "10.17.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.4.tgz#8993a4fe3c4022fda66bf4ea660d615fc5659c6f"
integrity sha512-F2pgg+LcIr/elguz+x+fdBX5KeZXGUOp7TV8M0TVIrDezYLFRNt8oMTyps0VQ1kj5WGGoR18RdxnRDHXrIFHMQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
agent-base@4:
version "4.2.1"
+1 -1
View File
@@ -14,4 +14,4 @@
"preLaunchTask": "npm"
}
]
}
}
@@ -46,6 +46,7 @@ interface Settings {
json?: {
schemas?: JSONSchemaSettings[];
format?: { enable: boolean; };
resultLimit?: number;
};
http?: {
proxy?: string;
@@ -142,12 +143,6 @@ export function activate(context: ExtensionContext) {
let disposable = client.start();
toDispose.push(disposable);
client.onReady().then(() => {
disposable = client.onTelemetry(e => {
if (telemetryReporter) {
telemetryReporter.sendTelemetryEvent(e.key, e.data);
}
});
const schemaDocuments: { [uri: string]: boolean } = {};
// handle content request
@@ -161,11 +156,23 @@ export function activate(context: ExtensionContext) {
return Promise.reject(error);
});
} else {
if (telemetryReporter && uri.authority === 'schema.management.azure.com') {
/* __GDPR__
"json.schema" : {
"schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
telemetryReporter.sendTelemetryEvent('json.schema', { schemaURL: uriPath });
}
const headers = { 'Accept-Encoding': 'gzip, deflate' };
return xhr({ url: uriPath, followRedirects: 5, headers }).then(response => {
return response.responseText;
}, (error: XHRResponse) => {
return Promise.reject(new ResponseError(error.status, error.responseText || getErrorStatusDescription(error.status) || error.toString()));
let extraInfo = error.responseText || error.toString();
if (extraInfo.length > 256) {
extraInfo = `${extraInfo.substr(0, 256)}...`;
}
return Promise.reject(new ResponseError(error.status, getErrorStatusDescription(error.status) + '\n' + extraInfo));
});
}
});
@@ -320,6 +327,7 @@ function getSettings(): Settings {
},
json: {
schemas: [],
resultLimit: 5000
}
};
let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
@@ -102,12 +102,12 @@
}
},
"dependencies": {
"request-light": "^0.2.4",
"request-light": "^0.2.5",
"vscode-extension-telemetry": "0.1.1",
"vscode-languageclient": "^6.0.0-next.1",
"vscode-languageclient": "^6.0.0-next.3",
"vscode-nls": "^4.1.1"
},
"devDependencies": {
"@types/node": "^10.14.8"
"@types/node": "^12.11.7"
}
}
@@ -12,16 +12,15 @@
},
"main": "./out/jsonServerMain",
"dependencies": {
"jsonc-parser": "^2.1.1",
"request-light": "^0.2.4",
"vscode-json-languageservice": "^3.3.5",
"vscode-languageserver": "^6.0.0-next.1",
"vscode-nls": "^4.1.1",
"vscode-uri": "^2.0.3"
"jsonc-parser": "^2.2.0",
"request-light": "^0.2.5",
"vscode-json-languageservice": "^3.4.7",
"vscode-languageserver": "^6.0.0-next.3",
"vscode-uri": "^2.1.1"
},
"devDependencies": {
"@types/mocha": "2.2.33",
"@types/node": "^10.14.8"
"@types/node": "^12.11.7"
},
"scripts": {
"prepublishOnly": "npm run clean && npm run compile",
@@ -5,16 +5,18 @@
import {
createConnection, IConnection,
TextDocuments, TextDocument, InitializeParams, InitializeResult, NotificationType, RequestType,
DocumentRangeFormattingRequest, Disposable, ServerCapabilities, Diagnostic
TextDocuments, InitializeParams, InitializeResult, NotificationType, RequestType,
DocumentRangeFormattingRequest, Disposable, ServerCapabilities, TextDocumentSyncKind
} from 'vscode-languageserver';
import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light';
import * as fs from 'fs';
import { URI } from 'vscode-uri';
import * as URL from 'url';
import { posix } from 'path';
import { setTimeout, clearTimeout } from 'timers';
import { formatError, runSafe, runSafeAsync } from './utils/runner';
import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration, ClientCapabilities } from 'vscode-json-languageservice';
import { TextDocument, JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration, ClientCapabilities, SchemaRequestService, Diagnostic } from 'vscode-json-languageservice';
import { getLanguageModelCache } from './languageModelCache';
interface ISchemaAssociations {
@@ -56,40 +58,40 @@ const workspaceContext = {
return URL.resolve(resource, relativePath);
}
};
function getSchemaRequestService(handledSchemas: { [schema: string]: boolean }) {
const fileRequestService: SchemaRequestService = (uri: string) => {
const fsPath = URI.parse(uri).fsPath;
return new Promise<string>((c, e) => {
fs.readFile(fsPath, 'UTF-8', (err, result) => {
err ? e(err.message || err.toString()) : c(result.toString());
});
});
};
const httpRequestService: SchemaRequestService = (uri: string) => {
const headers = { 'Accept-Encoding': 'gzip, deflate' };
return xhr({ url: uri, followRedirects: 5, headers }).then(response => {
return response.responseText;
}, (error: XHRResponse) => {
return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString());
});
};
function getSchemaRequestService(handledSchemas: string[] = ['https', 'http', 'file']) {
const builtInHandlers: { [protocol: string]: SchemaRequestService } = {};
for (let protocol of handledSchemas) {
if (protocol === 'file') {
builtInHandlers[protocol] = fileRequestService;
} else if (protocol === 'http' || protocol === 'https') {
builtInHandlers[protocol] = httpRequestService;
}
}
return (uri: string): Thenable<string> => {
const protocol = uri.substr(0, uri.indexOf(':'));
if (!handledSchemas || handledSchemas[protocol]) {
if (protocol === 'file') {
const fsPath = URI.parse(uri).fsPath;
return new Promise<string>((c, e) => {
fs.readFile(fsPath, 'UTF-8', (err, result) => {
err ? e(err.message || err.toString()) : c(result.toString());
});
});
} else if (protocol === 'http' || protocol === 'https') {
if (uri.indexOf('//schema.management.azure.com/') !== -1) {
/* __GDPR__
"json.schema" : {
"schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
connection.telemetry.logEvent({
key: 'json.schema',
value: {
schemaURL: uri
}
});
}
const headers = { 'Accept-Encoding': 'gzip, deflate' };
return xhr({ url: uri, followRedirects: 5, headers }).then(response => {
return response.responseText;
}, (error: XHRResponse) => {
return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString());
});
}
const builtInHandler = builtInHandlers[protocol];
if (builtInHandler) {
return builtInHandler(uri);
}
return connection.sendRequest(VSCodeContentRequest.type, uri).then(responseText => {
return responseText;
@@ -107,7 +109,7 @@ let languageService = getLanguageService({
});
// Create a text document manager.
const documents: TextDocuments = new TextDocuments();
const documents = new TextDocuments(TextDocument);
// Make the text document manager listen on the connection
// for open, change and close text document events
@@ -115,9 +117,12 @@ documents.listen(connection);
let clientSnippetSupport = false;
let dynamicFormatterRegistration = false;
let foldingRangeLimit = Number.MAX_VALUE;
let hierarchicalDocumentSymbolSupport = false;
let foldingRangeLimitDefault = Number.MAX_VALUE;
let foldingRangeLimit = Number.MAX_VALUE;
let resultLimit = Number.MAX_VALUE;
// After the server has started the client sends an initialize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilities.
connection.onInitialize((params: InitializeParams): InitializeResult => {
@@ -145,11 +150,10 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
clientSnippetSupport = getClientCapability('textDocument.completion.completionItem.snippetSupport', false);
dynamicFormatterRegistration = getClientCapability('textDocument.rangeFormatting.dynamicRegistration', false) && (typeof params.initializationOptions.provideFormatter !== 'boolean');
foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE);
foldingRangeLimitDefault = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE);
hierarchicalDocumentSymbolSupport = getClientCapability('textDocument.documentSymbol.hierarchicalDocumentSymbolSupport', false);
const capabilities: ServerCapabilities = {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
textDocumentSync: TextDocumentSyncKind.Incremental,
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : undefined,
hoverProvider: true,
documentSymbolProvider: true,
@@ -169,6 +173,7 @@ interface Settings {
json: {
schemas: JSONSchemaSettings[];
format: { enable: boolean; };
resultLimit?: number;
};
http: {
proxy: string;
@@ -182,6 +187,39 @@ interface JSONSchemaSettings {
schema?: JSONSchema;
}
namespace LimitExceededWarnings {
const pendingWarnings: { [uri: string]: { features: { [name: string]: string }; timeout?: NodeJS.Timeout; } } = {};
export function cancel(uri: string) {
const warning = pendingWarnings[uri];
if (warning && warning.timeout) {
clearTimeout(warning.timeout);
delete pendingWarnings[uri];
}
}
export function onResultLimitExceeded(uri: string, resultLimit: number, name: string) {
return () => {
let warning = pendingWarnings[uri];
if (warning) {
if (!warning.timeout) {
// already shown
return;
}
warning.features[name] = name;
warning.timeout.refresh();
} else {
warning = { features: { [name]: name } };
warning.timeout = setTimeout(() => {
connection.window.showInformationMessage(`${posix.basename(uri)}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
warning.timeout = undefined;
}, 2000);
pendingWarnings[uri] = warning;
}
};
}
}
let jsonConfigurationSettings: JSONSchemaSettings[] | undefined = undefined;
let schemaAssociations: ISchemaAssociations | undefined = undefined;
let formatterRegistration: Thenable<Disposable> | null = null;
@@ -194,6 +232,9 @@ connection.onDidChangeConfiguration((change) => {
jsonConfigurationSettings = settings.json && settings.json.schemas;
updateConfiguration();
foldingRangeLimit = Math.trunc(Math.max(settings.json && settings.json.resultLimit || foldingRangeLimitDefault, 0));
resultLimit = Math.trunc(Math.max(settings.json && settings.json.resultLimit || Number.MAX_VALUE, 0));
// dynamically enable & disable the formatter
if (dynamicFormatterRegistration) {
const enableFormatter = settings && settings.json && settings.json.format && settings.json.format.enable;
@@ -270,11 +311,13 @@ function updateConfiguration() {
// The content of a text document has changed. This event is emitted
// when the text document first opened or when its content has changed.
documents.onDidChangeContent((change) => {
LimitExceededWarnings.cancel(change.document.uri);
triggerValidation(change.document);
});
// a document has closed: clear all diagnostics
documents.onDidClose(event => {
LimitExceededWarnings.cancel(event.document.uri);
cleanPendingValidation(event.document);
connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] });
});
@@ -383,10 +426,11 @@ connection.onDocumentSymbol((documentSymbolParams, token) => {
const document = documents.get(documentSymbolParams.textDocument.uri);
if (document) {
const jsonDocument = getJSONDocument(document);
const onResultLimitExceeded = LimitExceededWarnings.onResultLimitExceeded(document.uri, resultLimit, 'document symbols');
if (hierarchicalDocumentSymbolSupport) {
return languageService.findDocumentSymbols2(document, jsonDocument);
return languageService.findDocumentSymbols2(document, jsonDocument, { resultLimit, onResultLimitExceeded });
} else {
return languageService.findDocumentSymbols(document, jsonDocument);
return languageService.findDocumentSymbols(document, jsonDocument, { resultLimit, onResultLimitExceeded });
}
}
return [];
@@ -407,8 +451,9 @@ connection.onDocumentColor((params, token) => {
return runSafeAsync(async () => {
const document = documents.get(params.textDocument.uri);
if (document) {
const onResultLimitExceeded = LimitExceededWarnings.onResultLimitExceeded(document.uri, resultLimit, 'document colors');
const jsonDocument = getJSONDocument(document);
return languageService.findDocumentColors(document, jsonDocument);
return languageService.findDocumentColors(document, jsonDocument, { resultLimit, onResultLimitExceeded });
}
return [];
}, [], `Error while computing document colors for ${params.textDocument.uri}`, token);
@@ -429,7 +474,8 @@ connection.onFoldingRanges((params, token) => {
return runSafe(() => {
const document = documents.get(params.textDocument.uri);
if (document) {
return languageService.getFoldingRanges(document, { rangeLimit: foldingRangeLimit });
const onRangeLimitExceeded = LimitExceededWarnings.onResultLimitExceeded(document.uri, foldingRangeLimit, 'folding ranges');
return languageService.getFoldingRanges(document, { rangeLimit: foldingRangeLimit, onRangeLimitExceeded });
}
return null;
}, null, `Error while computing folding ranges for ${params.textDocument.uri}`, token);
@@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.33.tgz#d79a0061ec270379f4d9e225f4096fb436669def"
integrity sha1-15oAYewnA3n02eIl9AlvtDZmne8=
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
agent-base@4:
version "4.1.2"
@@ -53,7 +53,7 @@ http-proxy-agent@^2.1.0:
agent-base "4"
debug "3.1.0"
https-proxy-agent@^2.2.1:
https-proxy-agent@^2.2.3:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
@@ -61,77 +61,77 @@ https-proxy-agent@^2.2.1:
agent-base "^4.3.0"
debug "^3.1.0"
jsonc-parser@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.1.1.tgz#83dc3d7a6e7186346b889b1280eefa04446c6d3e"
integrity sha512-VC0CjnWJylKB1iov4u76/W/5Ef0ydDkjtYWxoZ9t3HdWlSnZQwZL5MgFikaB/EtQ4RmMEw3tmQzuYnZA2/Ja1g==
jsonc-parser@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.0.tgz#f206f87f9d49d644b7502052c04e82dd6392e9ef"
integrity sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
request-light@^0.2.4:
version "0.2.4"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.4.tgz#3cea29c126682e6bcadf7915353322eeba01a755"
integrity sha512-pM9Fq5jRnSb+82V7M97rp8FE9/YNeP2L9eckB4Szd7lyeclSIx02aIpPO/6e4m6Dy31+FBN/zkFMTd2HkNO3ow==
request-light@^0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.1"
vscode-nls "^4.0.0"
vscode-json-languageservice@^3.3.5:
version "3.3.5"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.5.tgz#e222e8391beeb23cfa40cf17fd57d1594d295fc7"
integrity sha512-Le6SG5aRdrRc5jVeVMRkYbGH9rrVaZHCW0Oa8zCFQ0T8viUud9qdZ29lSv5NPNLwTB8mn4pYucFyyEPM2YWvLA==
dependencies:
jsonc-parser "^2.1.1"
vscode-languageserver-types "^3.15.0-next.5"
https-proxy-agent "^2.2.3"
vscode-nls "^4.1.1"
vscode-uri "^2.0.3"
vscode-json-languageservice@^3.4.7:
version "3.4.7"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.7.tgz#8d85f3c1d46a1e58e9867d747552fb8c83d934fd"
integrity sha512-y3MN2+/yph3yoIHGmHu4ScYpm285L58XVvfGkd49xTQzLja4apxSbwzsYcP9QsqS0W7KuvoyiPhqksiudoMwjg==
dependencies:
jsonc-parser "^2.2.0"
vscode-languageserver-textdocument "^1.0.0-next.4"
vscode-languageserver-types "^3.15.0-next.6"
vscode-nls "^4.1.1"
vscode-uri "^2.1.0"
vscode-jsonrpc@^5.0.0-next.2:
version "5.0.0-next.2"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca"
integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==
vscode-languageserver-protocol@^3.15.0-next.9:
version "3.15.0-next.9"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30"
integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g==
vscode-languageserver-protocol@^3.15.0-next.10:
version "3.15.0-next.10"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.10.tgz#f1382f0c270ae5d0c2c7e552483285fb75810914"
integrity sha512-TmbBhKrBoYNX+/pQGwoXmy2qlOfjGBUhwUGIzQoWpj8qtDzYuLof8bi19rGLZ9sVuSHh3anvIyVpGJEqT0QODQ==
dependencies:
vscode-jsonrpc "^5.0.0-next.2"
vscode-languageserver-types "^3.15.0-next.5"
vscode-languageserver-types "^3.15.0-next.6"
vscode-languageserver-types@^3.15.0-next.5:
version "3.15.0-next.5"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b"
integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw==
vscode-languageserver-textdocument@^1.0.0-next.4:
version "1.0.0-next.4"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.0-next.4.tgz#8f7afdfe3e81411f57baaa29bb3214d1907160cd"
integrity sha512-LJ5WfoBO54nqinjlLJKnjoo2Im4bIvPJ8bFT7R0C84ZI36iK8M29ddslfe5jUeWNSTtCda7YuKdKsDIq38HpgA==
vscode-languageserver@^6.0.0-next.1:
version "6.0.0-next.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.1.tgz#4d71886d4a17d22eafc61b3a5fbf84e8e27c191f"
integrity sha512-LSF6bXoFeXfMPRNyqzI3yFX/kD2DzXBemqvyj1kDWNVraiWttm4xKF4YXsvJ7Z3s9sVt/Dpu3CFU3w61PGNZMg==
vscode-languageserver-types@^3.15.0-next.6:
version "3.15.0-next.6"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.6.tgz#7a990d00c39ad4e744335afb4cc422a3e687ff25"
integrity sha512-+4jfvmZ26oFMSX6EgPRB75PWHoT8pzyWuSSWk0erC4hTzmJq2gWxVLh20bZutZjMmiivawvPshtM3XZhX2SttA==
vscode-languageserver@^6.0.0-next.3:
version "6.0.0-next.3"
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.3.tgz#41e2fda6417939792f6a19fc19ecbb2f080e2072"
integrity sha512-Q6T+KwYuoXV9KRHD6x7RfTU13pV0xAX2BtcuvSC/LBCiVAnEIOe7jKZjzya+B9gDvSk4hpfvhPefy5IdQK1mpQ==
dependencies:
vscode-languageserver-protocol "^3.15.0-next.9"
vscode-textbuffer "^1.0.0"
vscode-nls@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
vscode-languageserver-protocol "^3.15.0-next.10"
vscode-nls@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==
vscode-textbuffer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086"
integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow==
vscode-uri@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.0.tgz#475a4269e63edbc13914b40c84bc1416e3398156"
integrity sha512-3voe44nOhb6OdKlpZShVsmVvY2vFQHMe6REP3Ky9RVJuPyM/XidsjH6HncCIDdSmbcF5YQHrTC/Q+Q2loJGkOw==
vscode-uri@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543"
integrity sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw==
vscode-uri@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.1.tgz#5aa1803391b6ebdd17d047f51365cf62c38f6e90"
integrity sha512-eY9jmGoEnVf8VE8xr5znSah7Qt1P/xsCdErz+g8HYZtJ7bZqKH5E3d+6oVNm1AC/c6IHUDokbmVXKOi4qPAC9A==
+25 -30
View File
@@ -2,10 +2,10 @@
# yarn lockfile v1
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
agent-base@4:
version "4.2.1"
@@ -76,7 +76,7 @@ http-proxy-agent@^2.1.0:
agent-base "4"
debug "3.1.0"
https-proxy-agent@^2.2.1:
https-proxy-agent@^2.2.3:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
@@ -94,14 +94,14 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
request-light@^0.2.4:
version "0.2.4"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.4.tgz#3cea29c126682e6bcadf7915353322eeba01a755"
integrity sha512-pM9Fq5jRnSb+82V7M97rp8FE9/YNeP2L9eckB4Szd7lyeclSIx02aIpPO/6e4m6Dy31+FBN/zkFMTd2HkNO3ow==
request-light@^0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.1"
vscode-nls "^4.0.0"
https-proxy-agent "^2.2.3"
vscode-nls "^4.1.1"
semver@^5.3.0:
version "5.5.0"
@@ -125,31 +125,26 @@ vscode-jsonrpc@^5.0.0-next.2:
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca"
integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==
vscode-languageclient@^6.0.0-next.1:
version "6.0.0-next.1"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.1.tgz#deca1743afd20da092e04e40ef73cedbbd978455"
integrity sha512-eJ9VjLFNINArgRzLbQ11YlWry7dM93GEODkQBXTRfrSypksiO9qSGr4SHhWgxxP26p4FRSpzc/17+N+Egnnchg==
vscode-languageclient@^6.0.0-next.3:
version "6.0.0-next.3"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.3.tgz#41b701d963fc7affc01e9279532a747fcd4f3810"
integrity sha512-SuSaG9xjqkROm4Ie0jQig0CFDuU/WxHERegl3kRsFHDbhMSK4dH45ZeBY5zMWUgZ+LrIrEbwf8qWNlrTRBlUgg==
dependencies:
semver "^6.3.0"
vscode-languageserver-protocol "^3.15.0-next.9"
vscode-languageserver-protocol "^3.15.0-next.10"
vscode-languageserver-protocol@^3.15.0-next.9:
version "3.15.0-next.9"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30"
integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g==
vscode-languageserver-protocol@^3.15.0-next.10:
version "3.15.0-next.10"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.10.tgz#f1382f0c270ae5d0c2c7e552483285fb75810914"
integrity sha512-TmbBhKrBoYNX+/pQGwoXmy2qlOfjGBUhwUGIzQoWpj8qtDzYuLof8bi19rGLZ9sVuSHh3anvIyVpGJEqT0QODQ==
dependencies:
vscode-jsonrpc "^5.0.0-next.2"
vscode-languageserver-types "^3.15.0-next.5"
vscode-languageserver-types "^3.15.0-next.6"
vscode-languageserver-types@^3.15.0-next.5:
version "3.15.0-next.5"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b"
integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw==
vscode-nls@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
vscode-languageserver-types@^3.15.0-next.6:
version "3.15.0-next.6"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.6.tgz#7a990d00c39ad4e744335afb4cc422a3e687ff25"
integrity sha512-+4jfvmZ26oFMSX6EgPRB75PWHoT8pzyWuSSWk0erC4hTzmJq2gWxVLh20bZutZjMmiivawvPshtM3XZhX2SttA==
vscode-nls@^4.1.1:
version "4.1.1"
@@ -5,7 +5,7 @@
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/Microsoft/vscode-JSON.tmLanguage/commit/9bd83f1c252b375e957203f21793316203f61f70",
"name": "JSON (JavaScript Next)",
"name": "JSON (Javascript Next)",
"scopeName": "source.json",
"patterns": [
{
@@ -210,4 +210,4 @@
]
}
}
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
"compile": "gulp compile-extension:liveshare"
},
"devDependencies": {
"@types/node": "12.0.9",
"@types/node": "^12.11.7",
"ts-loader": "^5.3.3",
"tslint": "^5.12.1",
"typescript": "^3.3.1"
+4 -4
View File
@@ -18,10 +18,10 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@types/node@12.0.9":
version "12.0.9"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.9.tgz#18e0fc7bc6acc71f43a1a6ec9096c30d3954dd5c"
integrity sha512-xxrghIb6jMoEkNtdzGMUezwCEGuBd4QSA/Fko1XaUYpn6P/LwVw7UGpf4NzwGZXRC96fDgBJcBX7bXU0T52nWA==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
ansi-styles@^3.2.1:
version "3.2.1"
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/46724e2885f9557400ed91727d75c3574ceded3a",
"version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/e3091a421bdcad527018c897652ded47585cbd12",
"name": "Markdown",
"scopeName": "text.html.markdown",
"patterns": [
@@ -63,7 +63,7 @@
"while": "(^|\\G)\\s*(>) ?"
},
"fenced_code_block_css": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(css|css.erb)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(css|css.erb)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -96,7 +96,7 @@
]
},
"fenced_code_block_basic": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(html|htm|shtml|xhtml|inc|tmpl|tpl)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(html|htm|shtml|xhtml|inc|tmpl|tpl)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -129,7 +129,7 @@
]
},
"fenced_code_block_ini": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ini|conf)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ini|conf)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -162,7 +162,7 @@
]
},
"fenced_code_block_java": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(java|bsh)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(java|bsh)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -195,7 +195,7 @@
]
},
"fenced_code_block_lua": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(lua)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(lua)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -228,7 +228,7 @@
]
},
"fenced_code_block_makefile": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(Makefile|makefile|GNUmakefile|OCamlMakefile)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(Makefile|makefile|GNUmakefile|OCamlMakefile)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -261,7 +261,7 @@
]
},
"fenced_code_block_perl": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl|pl|pm|pod|t|PL|psgi|vcl)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl|pl|pm|pod|t|PL|psgi|vcl)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -294,7 +294,7 @@
]
},
"fenced_code_block_r": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(R|r|s|S|Rprofile|\\{\\.r.+?\\})(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(R|r|s|S|Rprofile|\\{\\.r.+?\\})((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -327,7 +327,7 @@
]
},
"fenced_code_block_ruby": {
"begin": "(^|\\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+[^`~]*)?$)",
"begin": "(^|\\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+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -360,7 +360,7 @@
]
},
"fenced_code_block_php": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(php|php3|php4|php5|phpt|phtml|aw|ctp)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(php|php3|php4|php5|phpt|phtml|aw|ctp)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -396,7 +396,7 @@
]
},
"fenced_code_block_sql": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(sql|ddl|dml)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(sql|ddl|dml)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -429,7 +429,7 @@
]
},
"fenced_code_block_vs_net": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(vb)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(vb)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -462,7 +462,7 @@
]
},
"fenced_code_block_xml": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xml|xsd|tld|jsp|pt|cpt|dtml|rss|opml)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xml|xsd|tld|jsp|pt|cpt|dtml|rss|opml)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -495,7 +495,7 @@
]
},
"fenced_code_block_xsl": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xsl|xslt)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xsl|xslt)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -528,7 +528,7 @@
]
},
"fenced_code_block_yaml": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(yaml|yml)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(yaml|yml)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -561,7 +561,7 @@
]
},
"fenced_code_block_dosbatch": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(bat|batch)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(bat|batch)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -594,7 +594,7 @@
]
},
"fenced_code_block_clojure": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(clj|cljs|clojure)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(clj|cljs|clojure)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -627,7 +627,7 @@
]
},
"fenced_code_block_coffee": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(coffee|Cakefile|coffee.erb)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(coffee|Cakefile|coffee.erb)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -660,7 +660,7 @@
]
},
"fenced_code_block_c": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(c|h)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(c|h)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -693,7 +693,7 @@
]
},
"fenced_code_block_cpp": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cpp|c\\+\\+|cxx)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cpp|c\\+\\+|cxx)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -726,7 +726,7 @@
]
},
"fenced_code_block_diff": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(patch|diff|rej)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(patch|diff|rej)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -759,7 +759,7 @@
]
},
"fenced_code_block_dockerfile": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dockerfile|Dockerfile)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dockerfile|Dockerfile)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -792,7 +792,7 @@
]
},
"fenced_code_block_git_commit": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(COMMIT_EDITMSG|MERGE_MSG)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(COMMIT_EDITMSG|MERGE_MSG)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -825,7 +825,7 @@
]
},
"fenced_code_block_git_rebase": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(git-rebase-todo)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(git-rebase-todo)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -858,7 +858,7 @@
]
},
"fenced_code_block_go": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(go|golang)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(go|golang)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -891,7 +891,7 @@
]
},
"fenced_code_block_groovy": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(groovy|gvy)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(groovy|gvy)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -924,7 +924,7 @@
]
},
"fenced_code_block_pug": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jade|pug)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jade|pug)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -957,7 +957,7 @@
]
},
"fenced_code_block_js": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(js|jsx|javascript|es6|mjs|\\{\\.js.+?\\})(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(js|jsx|javascript|es6|mjs|cjs|\\{\\.js.+?\\})((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -990,7 +990,7 @@
]
},
"fenced_code_block_js_regexp": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(regexp)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(regexp)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1023,7 +1023,7 @@
]
},
"fenced_code_block_json": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(json|json5|sublime-settings|sublime-menu|sublime-keymap|sublime-mousemap|sublime-theme|sublime-build|sublime-project|sublime-completions)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(json|json5|sublime-settings|sublime-menu|sublime-keymap|sublime-mousemap|sublime-theme|sublime-build|sublime-project|sublime-completions)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1056,7 +1056,7 @@
]
},
"fenced_code_block_jsonc": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jsonc)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jsonc)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1089,7 +1089,7 @@
]
},
"fenced_code_block_less": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(less)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(less)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1122,7 +1122,7 @@
]
},
"fenced_code_block_objc": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(objectivec|objective-c|mm|objc|obj-c|m|h)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(objectivec|objective-c|mm|objc|obj-c|m|h)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1155,7 +1155,7 @@
]
},
"fenced_code_block_swift": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(swift)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(swift)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1188,7 +1188,7 @@
]
},
"fenced_code_block_scss": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scss)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scss)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1221,7 +1221,7 @@
]
},
"fenced_code_block_perl6": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl6|p6|pl6|pm6|nqp)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl6|p6|pl6|pm6|nqp)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1254,7 +1254,7 @@
]
},
"fenced_code_block_powershell": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(powershell|ps1|psm1|psd1)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(powershell|ps1|psm1|psd1)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1287,7 +1287,7 @@
]
},
"fenced_code_block_python": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(python|py|py3|rpy|pyw|cpy|SConstruct|Sconstruct|sconstruct|SConscript|gyp|gypi|\\{\\.python.+?\\})(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(python|py|py3|rpy|pyw|cpy|SConstruct|Sconstruct|sconstruct|SConscript|gyp|gypi|\\{\\.python.+?\\})((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1320,7 +1320,7 @@
]
},
"fenced_code_block_regexp_python": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(re)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(re)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1353,7 +1353,7 @@
]
},
"fenced_code_block_rust": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(rust|rs|\\{\\.rust.+?\\})(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(rust|rs|\\{\\.rust.+?\\})((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1386,7 +1386,7 @@
]
},
"fenced_code_block_scala": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scala|sbt)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scala|sbt)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1419,7 +1419,7 @@
]
},
"fenced_code_block_shell": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(shell|sh|bash|zsh|bashrc|bash_profile|bash_login|profile|bash_logout|.textmate_init|\\{\\.bash.+?\\})(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(shell|sh|bash|zsh|bashrc|bash_profile|bash_login|profile|bash_logout|.textmate_init|\\{\\.bash.+?\\})((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1452,7 +1452,7 @@
]
},
"fenced_code_block_ts": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(typescript|ts)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(typescript|ts)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1485,7 +1485,7 @@
]
},
"fenced_code_block_tsx": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(tsx)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(tsx)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1518,7 +1518,7 @@
]
},
"fenced_code_block_csharp": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cs|csharp|c#)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cs|csharp|c#)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1551,7 +1551,7 @@
]
},
"fenced_code_block_fsharp": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(fs|fsharp|f#)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(fs|fsharp|f#)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1584,7 +1584,7 @@
]
},
"fenced_code_block_dart": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dart)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dart)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1617,7 +1617,7 @@
]
},
"fenced_code_block_handlebars": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(handlebars|hbs)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(handlebars|hbs)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1650,7 +1650,7 @@
]
},
"fenced_code_block_markdown": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(markdown|md)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(markdown|md)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -1683,7 +1683,7 @@
]
},
"fenced_code_block_log": {
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(log)(\\s+[^`~]*)?$)",
"begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(log)((\\s+|:|\\{)[^`~]*)?$)",
"name": "markup.fenced_code.block.markdown",
"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
"beginCaptures": {
@@ -2623,4 +2623,4 @@
"name": "markup.inline.raw.string.markdown"
}
}
}
}
File diff suppressed because one or more lines are too long
@@ -129,15 +129,6 @@ h1, h2, h3 {
font-weight: normal;
}
h1 code,
h2 code,
h3 code,
h4 code,
h5 code,
h6 code {
line-height: auto;
}
table {
border-collapse: collapse;
}
File diff suppressed because one or more lines are too long
@@ -25,7 +25,9 @@
"onCommand:markdown.showSource",
"onCommand:markdown.showPreviewSecuritySelector",
"onCommand:markdown.api.render",
"onWebviewPanel:markdown.preview"
"onCommand:notebook.showPreview",
"onWebviewPanel:markdown.preview",
"onWebviewEditor:vscode.markdown.preview.editor"
],
"contributes": {
"commands": [
@@ -307,6 +309,18 @@
],
"markdown.previewScripts": [
"./media/index.js"
],
"webviewEditors": [
{
"viewType": "vscode.markdown.preview.editor",
"displayName": "(Experimental) VS Code Markdown Preview",
"priority": "option",
"selector": [
{
"filenamePattern": "*.md"
}
]
}
]
},
"scripts": {
@@ -327,14 +341,14 @@
"@types/highlight.js": "9.12.3",
"@types/lodash.throttle": "^4.1.3",
"@types/markdown-it": "0.0.2",
"@types/node": "^10.14.8",
"@types/node": "^12.11.7",
"lodash.throttle": "^4.1.1",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"ts-loader": "^4.0.1",
"typescript": "^3.3.1",
"ts-loader": "^6.2.1",
"typescript": "^3.7.2",
"vscode": "^1.1.10",
"webpack": "^4.1.0",
"webpack-cli": "^2.0.10"
"webpack": "^4.41.2",
"webpack-cli": "^3.3.0"
}
}
@@ -129,7 +129,7 @@ document.addEventListener('dblclick', event => {
}
});
const passThroughLinkSchemes = ['http:', 'https:', 'mailto:', 'vscode:', 'vscode-insiders'];
const passThroughLinkSchemes = ['http:', 'https:', 'mailto:', 'vscode:', 'vscode-insiders:'];
document.addEventListener('click', event => {
if (!event) {
@@ -5,6 +5,7 @@
import { getSettings } from './settings';
const codeLineClass = 'code-line';
function clamp(min: number, max: number, value: number) {
return Math.min(max, Math.max(min, value));
@@ -25,9 +26,17 @@ const getCodeLineElements = (() => {
return () => {
if (!elements) {
elements = [{ element: document.body, line: 0 }];
for (const element of document.getElementsByClassName('code-line')) {
for (const element of document.getElementsByClassName(codeLineClass)) {
const line = +element.getAttribute('data-line')!;
if (!isNaN(line)) {
if (isNaN(line)) {
continue;
}
if (element.tagName === 'CODE' && element.parentElement && element.parentElement.tagName === 'PRE') {
// Fenched code blocks are a special case since the `code-line` can only be marked on
// the `<code>` element and not the parent `<pre>` element.
elements.push({ element: element.parentElement as HTMLElement, line });
} else {
elements.push({ element: element as HTMLElement, line });
}
}
@@ -67,7 +76,7 @@ export function getLineElementsAtPageOffset(offset: number): { previous: CodeLin
let hi = lines.length - 1;
while (lo + 1 < hi) {
const mid = Math.floor((lo + hi) / 2);
const bounds = lines[mid].element.getBoundingClientRect();
const bounds = getElementBounds(lines[mid]);
if (bounds.top + bounds.height >= position) {
hi = mid;
}
@@ -76,14 +85,35 @@ export function getLineElementsAtPageOffset(offset: number): { previous: CodeLin
}
}
const hiElement = lines[hi];
const hiBounds = hiElement.element.getBoundingClientRect();
const hiBounds = getElementBounds(hiElement);
if (hi >= 1 && hiBounds.top > position) {
const loElement = lines[lo];
return { previous: loElement, next: hiElement };
}
if (hi > 1 && hi < lines.length && hiBounds.top + hiBounds.height > position) {
return { previous: hiElement, next: lines[hi + 1] };
}
return { previous: hiElement };
}
function getElementBounds({ element }: CodeLineElement): { top: number, height: number } {
const myBounds = element.getBoundingClientRect();
// Some code line elements may contain other code line elements.
// In those cases, only take the height up to that child.
const codeLineChild = element.querySelector(`.${codeLineClass}`);
if (codeLineChild) {
const childBounds = codeLineChild.getBoundingClientRect();
const height = Math.max(1, (childBounds.top - myBounds.top));
return {
top: myBounds.top,
height: height
};
}
return myBounds;
}
/**
* Attempt to reveal the element for a source line in the editor.
*/
@@ -102,7 +132,7 @@ export function scrollToRevealSourceLine(line: number) {
return;
}
let scrollTo = 0;
const rect = previous.element.getBoundingClientRect();
const rect = getElementBounds(previous);
const previousTop = rect.top;
if (next && next.line !== previous.line) {
// Between two elements. Go to percentage offset between them.
@@ -119,14 +149,13 @@ export function scrollToRevealSourceLine(line: number) {
export function getEditorLineNumberForPageOffset(offset: number) {
const { previous, next } = getLineElementsAtPageOffset(offset);
if (previous) {
const previousBounds = previous.element.getBoundingClientRect();
const previousBounds = getElementBounds(previous);
const offsetFromPrevious = (offset - window.scrollY - previousBounds.top);
if (next) {
const progressBetweenElements = offsetFromPrevious / (next.element.getBoundingClientRect().top - previousBounds.top);
const progressBetweenElements = offsetFromPrevious / (getElementBounds(next).top - previousBounds.top);
const line = previous.line + progressBetweenElements * (next.line - previous.line);
return clampLine(line);
}
else {
} else {
const progressWithinElement = offsetFromPrevious / (previousBounds.height);
const line = previous.line + progressWithinElement;
return clampLine(line);
@@ -6,9 +6,8 @@
import * as vscode from 'vscode';
import { Command } from '../commandManager';
import { MarkdownPreviewManager } from '../features/previewManager';
import { MarkdownPreviewManager, DynamicPreviewSettings } from '../features/previewManager';
import { TelemetryReporter } from '../telemetryReporter';
import { PreviewSettings } from '../features/preview';
interface ShowPreviewSettings {
readonly sideBySide?: boolean;
@@ -39,7 +38,7 @@ async function showPreview(
}
const resourceColumn = (vscode.window.activeTextEditor && vscode.window.activeTextEditor.viewColumn) || vscode.ViewColumn.One;
webviewManager.preview(resource, {
webviewManager.openDynamicPreview(resource, {
resourceColumn: resourceColumn,
previewColumn: previewSettings.sideBySide ? resourceColumn + 1 : resourceColumn,
locked: !!previewSettings.locked
@@ -59,7 +58,7 @@ export class ShowPreviewCommand implements Command {
private readonly telemetryReporter: TelemetryReporter
) { }
public execute(mainUri?: vscode.Uri, allUris?: vscode.Uri[], previewSettings?: PreviewSettings) {
public execute(mainUri?: vscode.Uri, allUris?: vscode.Uri[], previewSettings?: DynamicPreviewSettings) {
for (const uri of Array.isArray(allUris) ? allUris : [mainUri]) {
showPreview(this.webviewManager, this.telemetryReporter, uri, {
sideBySide: false,
@@ -77,7 +76,7 @@ export class ShowPreviewToSideCommand implements Command {
private readonly telemetryReporter: TelemetryReporter
) { }
public execute(uri?: vscode.Uri, previewSettings?: PreviewSettings) {
public execute(uri?: vscode.Uri, previewSettings?: DynamicPreviewSettings) {
showPreview(this.webviewManager, this.telemetryReporter, uri, {
sideBySide: true,
locked: previewSettings && previewSettings.locked
@@ -54,9 +54,11 @@ function registerMarkdownLanguageFeatures(
{ language: 'markdown', scheme: 'untitled' }
];
const charPattern = '(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})';
return vscode.Disposable.from(
vscode.languages.setLanguageConfiguration('markdown', {
wordPattern: new RegExp('(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})+', 'ug'),
wordPattern: new RegExp(`${charPattern}((${charPattern}|[_])?${charPattern})*`, 'ug'),
}),
vscode.languages.registerDocumentSymbolProvider(selector, symbolProvider),
vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider()),
@@ -7,7 +7,7 @@ import * as path from 'path';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { OpenDocumentLinkCommand } from '../commands/openDocumentLink';
import { getUriForLinkWithKnownExternalScheme } from '../util/links';
import { getUriForLinkWithKnownExternalScheme, isOfScheme, Schemes } from '../util/links';
const localize = nls.loadMessageBundle();
@@ -18,6 +18,10 @@ function parseLink(
): { uri: vscode.Uri, tooltip?: string } {
const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link);
if (externalSchemeUri) {
// Normalize VS Code links to target currently running version
if (isOfScheme(Schemes.vscode, link) || isOfScheme(Schemes['vscode-insiders'], link)) {
return { uri: vscode.Uri.parse(link).with({ scheme: vscode.env.uriScheme }) };
}
return { uri: externalSchemeUri };
}
@@ -11,7 +11,7 @@ import { MarkdownContentProvider } from './previewContentProvider';
import { Disposable } from '../util/dispose';
import * as nls from 'vscode-nls';
import { getVisibleLine, MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor';
import { getVisibleLine, TopmostLineMonitor } from '../util/topmostLineMonitor';
import { MarkdownPreviewConfigurationManager } from './previewConfig';
import { MarkdownContributionProvider, MarkdownContributions } from '../markdownExtensions';
import { isMarkdownFile } from '../util/file';
@@ -72,11 +72,22 @@ export class PreviewDocumentVersion {
}
}
export class MarkdownPreview extends Disposable {
interface DynamicPreviewInput {
readonly resource: vscode.Uri;
readonly resourceColumn: vscode.ViewColumn;
readonly locked: boolean;
readonly line?: number;
}
export class DynamicMarkdownPreview extends Disposable {
public static readonly viewType = 'markdown.preview';
private readonly delay = 300;
private _resource: vscode.Uri;
private readonly _resourceColumn: vscode.ViewColumn;
private _locked: boolean;
private readonly editor: vscode.WebviewPanel;
@@ -84,92 +95,65 @@ export class MarkdownPreview extends Disposable {
private line: number | undefined = undefined;
private firstUpdate = true;
private currentVersion?: PreviewDocumentVersion;
private forceUpdate = false;
private isScrolling = false;
private _disposed: boolean = false;
private imageInfo: { id: string, width: number, height: number; }[] = [];
private scrollToFragment: string | undefined;
public static async revive(
public static revive(
input: DynamicPreviewInput,
webview: vscode.WebviewPanel,
state: any,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
topmostLineMonitor: MarkdownFileTopmostLineMonitor,
topmostLineMonitor: TopmostLineMonitor,
contributionProvider: MarkdownContributionProvider,
): Promise<MarkdownPreview> {
const resource = vscode.Uri.parse(state.resource);
const locked = state.locked;
const line = state.line;
const resourceColumn = state.resourceColumn;
): DynamicMarkdownPreview {
webview.webview.options = DynamicMarkdownPreview.getWebviewOptions(input.resource, contributionProvider.contributions);
webview.title = DynamicMarkdownPreview.getPreviewTitle(input.resource, input.locked);
const preview = new MarkdownPreview(
webview,
resource,
locked,
resourceColumn,
contentProvider,
previewConfigurations,
logger,
topmostLineMonitor,
contributionProvider);
preview.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, contributionProvider.contributions);
if (!isNaN(line)) {
preview.line = line;
}
await preview.doUpdate();
return preview;
return new DynamicMarkdownPreview(webview, input,
contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider);
}
public static create(
resource: vscode.Uri,
input: DynamicPreviewInput,
previewColumn: vscode.ViewColumn,
resourceColumn: vscode.ViewColumn,
locked: boolean,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
topmostLineMonitor: MarkdownFileTopmostLineMonitor,
topmostLineMonitor: TopmostLineMonitor,
contributionProvider: MarkdownContributionProvider
): MarkdownPreview {
): DynamicMarkdownPreview {
const webview = vscode.window.createWebviewPanel(
MarkdownPreview.viewType,
MarkdownPreview.getPreviewTitle(resource, locked),
DynamicMarkdownPreview.viewType,
DynamicMarkdownPreview.getPreviewTitle(input.resource, input.locked),
previewColumn, {
enableFindWidget: true,
...MarkdownPreview.getWebviewOptions(resource, contributionProvider.contributions)
...DynamicMarkdownPreview.getWebviewOptions(input.resource, contributionProvider.contributions)
});
return new MarkdownPreview(
webview,
resource,
locked,
resourceColumn,
contentProvider,
previewConfigurations,
logger,
topmostLineMonitor,
contributionProvider);
return new DynamicMarkdownPreview(webview, input,
contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider);
}
private constructor(
webview: vscode.WebviewPanel,
resource: vscode.Uri,
locked: boolean,
private readonly _resourceColumn: vscode.ViewColumn,
input: DynamicPreviewInput,
private readonly _contentProvider: MarkdownContentProvider,
private readonly _previewConfigurations: MarkdownPreviewConfigurationManager,
private readonly _logger: Logger,
topmostLineMonitor: MarkdownFileTopmostLineMonitor,
topmostLineMonitor: TopmostLineMonitor,
private readonly _contributionProvider: MarkdownContributionProvider,
) {
super();
this._resource = resource;
this._locked = locked;
this._resource = input.resource;
this._resourceColumn = input.resourceColumn;
this._locked = input.locked;
this.editor = webview;
if (!isNaN(input.line!)) {
this.line = input.line;
}
this._register(this.editor.onDidDispose(() => {
this.dispose();
@@ -190,7 +174,7 @@ export class MarkdownPreview extends Disposable {
switch (e.type) {
case 'cacheImageSizes':
this.onCacheImageSizes(e.body);
this.imageInfo = e.body;
break;
case 'revealLine':
@@ -221,7 +205,7 @@ export class MarkdownPreview extends Disposable {
}
}));
this._register(topmostLineMonitor.onDidChangeTopmostLine(event => {
this._register(topmostLineMonitor.onDidChanged(event => {
if (this.isPreviewOf(event.resource)) {
this.updateForView(event.resource, event.line);
}
@@ -239,9 +223,11 @@ export class MarkdownPreview extends Disposable {
this._register(vscode.window.onDidChangeActiveTextEditor(editor => {
if (editor && isMarkdownFile(editor.document) && !this._locked) {
this.update(editor.document.uri);
this.update(editor.document.uri, false);
}
}));
this.doUpdate();
}
private readonly _onDisposeEmitter = this._register(new vscode.EventEmitter<void>());
@@ -278,7 +264,6 @@ export class MarkdownPreview extends Disposable {
this._onDisposeEmitter.fire();
this._onDisposeEmitter.dispose();
this._onDidChangeViewStateEmitter.dispose();
this.editor.dispose();
super.dispose();
}
@@ -297,7 +282,6 @@ export class MarkdownPreview extends Disposable {
}
}
// If we have changed resources, cancel any pending updates
const isResourceChange = resource.fsPath !== this._resource.fsPath;
if (isResourceChange) {
@@ -310,9 +294,9 @@ export class MarkdownPreview extends Disposable {
// Schedule update if none is pending
if (!this.throttleTimer) {
if (isResourceChange || this.firstUpdate) {
this.doUpdate();
this.doUpdate(isRefresh);
} else {
this.throttleTimer = setTimeout(() => this.doUpdate(), 300);
this.throttleTimer = setTimeout(() => this.doUpdate(isRefresh), this.delay);
}
}
@@ -320,7 +304,6 @@ export class MarkdownPreview extends Disposable {
}
public refresh() {
this.forceUpdate = true;
this.update(this._resource, true);
}
@@ -350,7 +333,7 @@ export class MarkdownPreview extends Disposable {
}
}
public matches(otherPreview: MarkdownPreview): boolean {
public matches(otherPreview: DynamicMarkdownPreview): boolean {
return this.matchesResource(otherPreview._resource, otherPreview.position, otherPreview._locked);
}
@@ -360,7 +343,7 @@ export class MarkdownPreview extends Disposable {
public toggleLock() {
this._locked = !this._locked;
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
this.editor.title = DynamicMarkdownPreview.getPreviewTitle(this._resource, this._locked);
}
private get iconPath() {
@@ -408,7 +391,7 @@ export class MarkdownPreview extends Disposable {
}
}
private async doUpdate(): Promise<void> {
private async doUpdate(forceUpdate?: boolean): Promise<void> {
if (this._disposed) {
return;
}
@@ -431,13 +414,12 @@ export class MarkdownPreview extends Disposable {
}
const pendingVersion = new PreviewDocumentVersion(markdownResource, document.version);
if (!this.forceUpdate && this.currentVersion && this.currentVersion.equals(pendingVersion)) {
if (!forceUpdate && this.currentVersion?.equals(pendingVersion)) {
if (this.line) {
this.updateForView(markdownResource, this.line);
}
return;
}
this.forceUpdate = false;
this.currentVersion = pendingVersion;
if (this._resource === markdownResource) {
@@ -463,7 +445,7 @@ export class MarkdownPreview extends Disposable {
): vscode.WebviewOptions {
return {
enableScripts: true,
localResourceRoots: MarkdownPreview.getLocalResourceRoots(resource, contributions)
localResourceRoots: DynamicMarkdownPreview.getLocalResourceRoots(resource, contributions)
};
}
@@ -508,6 +490,9 @@ export class MarkdownPreview extends Disposable {
}
private async onDidClickPreview(line: number): Promise<void> {
// fix #82457, find currently opened but unfocused source tab
await vscode.commands.executeCommand('markdown.showSource');
for (const visibleEditor of vscode.window.visibleTextEditors) {
if (this.isPreviewOf(visibleEditor.document.uri)) {
const editor = await vscode.window.showTextDocument(visibleEditor.document, visibleEditor.viewColumn);
@@ -529,9 +514,9 @@ export class MarkdownPreview extends Disposable {
}
private setContent(html: string): void {
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
this.editor.title = DynamicMarkdownPreview.getPreviewTitle(this._resource, this._locked);
this.editor.iconPath = this.iconPath;
this.editor.webview.options = MarkdownPreview.getWebviewOptions(this._resource, this._contributionProvider.contributions);
this.editor.webview.options = DynamicMarkdownPreview.getWebviewOptions(this._resource, this._contributionProvider.contributions);
this.editor.webview.html = html;
}
@@ -559,14 +544,4 @@ export class MarkdownPreview extends Disposable {
vscode.commands.executeCommand('_markdown.openDocumentLink', { path: hrefPath, fragment, fromResource: this.resource });
}
private async onCacheImageSizes(imageInfo: { id: string, width: number, height: number; }[]) {
this.imageInfo = imageInfo;
}
}
export interface PreviewSettings {
readonly resourceColumn: vscode.ViewColumn;
readonly previewColumn: vscode.ViewColumn;
readonly locked: boolean;
}
@@ -7,19 +7,61 @@ import * as vscode from 'vscode';
import { Logger } from '../logger';
import { MarkdownContributionProvider } from '../markdownExtensions';
import { disposeAll, Disposable } from '../util/dispose';
import { MarkdownFileTopmostLineMonitor } from '../util/topmostLineMonitor';
import { MarkdownPreview, PreviewSettings } from './preview';
import { TopmostLineMonitor } from '../util/topmostLineMonitor';
import { DynamicMarkdownPreview } from './preview';
import { MarkdownPreviewConfigurationManager } from './previewConfig';
import { MarkdownContentProvider } from './previewContentProvider';
export interface DynamicPreviewSettings {
readonly resourceColumn: vscode.ViewColumn;
readonly previewColumn: vscode.ViewColumn;
readonly locked: boolean;
}
export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer {
class PreviewStore extends Disposable {
private readonly _previews = new Set<DynamicMarkdownPreview>();
public dispose(): void {
super.dispose();
for (const preview of this._previews) {
preview.dispose();
}
this._previews.clear();
}
[Symbol.iterator](): Iterator<DynamicMarkdownPreview> {
return this._previews[Symbol.iterator]();
}
public get(resource: vscode.Uri, previewSettings: DynamicPreviewSettings): DynamicMarkdownPreview | undefined {
for (const preview of this._previews) {
if (preview.matchesResource(resource, previewSettings.previewColumn, previewSettings.locked)) {
return preview;
}
}
return undefined;
}
public add(preview: DynamicMarkdownPreview) {
this._previews.add(preview);
}
public delete(preview: DynamicMarkdownPreview) {
this._previews.delete(preview);
}
}
export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer, vscode.WebviewEditorProvider {
private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus';
private readonly _topmostLineMonitor = new MarkdownFileTopmostLineMonitor();
private readonly _topmostLineMonitor = new TopmostLineMonitor();
private readonly _previewConfigurations = new MarkdownPreviewConfigurationManager();
private readonly _previews: MarkdownPreview[] = [];
private _activePreview: MarkdownPreview | undefined = undefined;
private readonly _dynamicPreviews = this._register(new PreviewStore());
private readonly _staticPreviews = this._register(new PreviewStore());
private _activePreview: DynamicMarkdownPreview | undefined = undefined;
public constructor(
private readonly _contentProvider: MarkdownContentProvider,
@@ -27,46 +69,48 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
private readonly _contributions: MarkdownContributionProvider
) {
super();
this._register(vscode.window.registerWebviewPanelSerializer(MarkdownPreview.viewType, this));
}
public dispose(): void {
super.dispose();
disposeAll(this._previews);
this._register(vscode.window.registerWebviewPanelSerializer(DynamicMarkdownPreview.viewType, this));
this._register(vscode.window.registerWebviewEditorProvider('vscode.markdown.preview.editor', this));
}
public refresh() {
for (const preview of this._previews) {
for (const preview of this._dynamicPreviews) {
preview.refresh();
}
for (const preview of this._staticPreviews) {
preview.refresh();
}
}
public updateConfiguration() {
for (const preview of this._previews) {
for (const preview of this._dynamicPreviews) {
preview.updateConfiguration();
}
for (const preview of this._staticPreviews) {
preview.updateConfiguration();
}
}
public preview(
public openDynamicPreview(
resource: vscode.Uri,
previewSettings: PreviewSettings
settings: DynamicPreviewSettings
): void {
let preview = this.getExistingPreview(resource, previewSettings);
let preview = this._dynamicPreviews.get(resource, settings);
if (preview) {
preview.reveal(previewSettings.previewColumn);
preview.reveal(settings.previewColumn);
} else {
preview = this.createNewPreview(resource, previewSettings);
preview = this.createNewDynamicPreview(resource, settings);
}
preview.update(resource);
}
public get activePreviewResource() {
return this._activePreview && this._activePreview.resource;
return this._activePreview?.resource;
}
public get activePreviewResourceColumn() {
return this._activePreview && this._activePreview.resourceColumn;
return this._activePreview?.resourceColumn;
}
public toggleLock() {
@@ -75,7 +119,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
preview.toggleLock();
// Close any previews that are now redundant, such as having two dynamic previews in the same editor group
for (const otherPreview of this._previews) {
for (const otherPreview of this._dynamicPreviews) {
if (otherPreview !== preview && preview.matches(otherPreview)) {
otherPreview.dispose();
}
@@ -87,35 +131,50 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
webview: vscode.WebviewPanel,
state: any
): Promise<void> {
const preview = await MarkdownPreview.revive(
const resource = vscode.Uri.parse(state.resource);
const locked = state.locked;
const line = state.line;
const resourceColumn = state.resourceColumn;
const preview = await DynamicMarkdownPreview.revive(
{ resource, locked, line, resourceColumn },
webview,
state,
this._contentProvider,
this._previewConfigurations,
this._logger,
this._topmostLineMonitor,
this._contributions);
this.registerPreview(preview);
this.registerDynamicPreview(preview);
}
private getExistingPreview(
resource: vscode.Uri,
previewSettings: PreviewSettings
): MarkdownPreview | undefined {
return this._previews.find(preview =>
preview.matchesResource(resource, previewSettings.previewColumn, previewSettings.locked));
public async resolveWebviewEditor(
input: { readonly resource: vscode.Uri; },
webview: vscode.WebviewPanel
): Promise<vscode.WebviewEditorCapabilities> {
const preview = DynamicMarkdownPreview.revive(
{ resource: input.resource, locked: false, resourceColumn: vscode.ViewColumn.One },
webview,
this._contentProvider,
this._previewConfigurations,
this._logger,
this._topmostLineMonitor,
this._contributions);
this.registerStaticPreview(preview);
return {};
}
private createNewPreview(
private createNewDynamicPreview(
resource: vscode.Uri,
previewSettings: PreviewSettings
): MarkdownPreview {
const preview = MarkdownPreview.create(
resource,
previewSettings: DynamicPreviewSettings
): DynamicMarkdownPreview {
const preview = DynamicMarkdownPreview.create(
{
resource,
resourceColumn: previewSettings.resourceColumn,
locked: previewSettings.locked,
},
previewSettings.previewColumn,
previewSettings.resourceColumn,
previewSettings.locked,
this._contentProvider,
this._previewConfigurations,
this._logger,
@@ -124,34 +183,48 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
this.setPreviewActiveContext(true);
this._activePreview = preview;
return this.registerPreview(preview);
return this.registerDynamicPreview(preview);
}
private registerPreview(
preview: MarkdownPreview
): MarkdownPreview {
this._previews.push(preview);
private registerDynamicPreview(preview: DynamicMarkdownPreview): DynamicMarkdownPreview {
this._dynamicPreviews.add(preview);
preview.onDispose(() => {
const existing = this._previews.indexOf(preview);
if (existing === -1) {
return;
}
this._dynamicPreviews.delete(preview);
});
this._previews.splice(existing, 1);
this.trackActive(preview);
preview.onDidChangeViewState(() => {
// Remove other dynamic previews in our column
disposeAll(Array.from(this._dynamicPreviews).filter(otherPreview => preview !== otherPreview && preview.matches(otherPreview)));
});
return preview;
}
private registerStaticPreview(preview: DynamicMarkdownPreview): DynamicMarkdownPreview {
this._staticPreviews.add(preview);
preview.onDispose(() => {
this._staticPreviews.delete(preview);
});
this.trackActive(preview);
return preview;
}
private trackActive(preview: DynamicMarkdownPreview): void {
preview.onDidChangeViewState(({ webviewPanel }) => {
this.setPreviewActiveContext(webviewPanel.active);
this._activePreview = webviewPanel.active ? preview : undefined;
});
preview.onDispose(() => {
if (this._activePreview === preview) {
this.setPreviewActiveContext(false);
this._activePreview = undefined;
}
});
preview.onDidChangeViewState(({ webviewPanel }) => {
disposeAll(this._previews.filter(otherPreview => preview !== otherPreview && preview!.matches(otherPreview)));
this.setPreviewActiveContext(webviewPanel.active);
this._activePreview = webviewPanel.active ? preview : undefined;
});
return preview;
}
private setPreviewActiveContext(value: boolean) {
@@ -41,13 +41,21 @@ export class Logger {
public log(message: string, data?: any): void {
if (this.trace === Trace.Verbose) {
this.appendLine(`[Log - ${(new Date().toLocaleTimeString())}] ${message}`);
this.appendLine(`[Log - ${this.now()}] ${message}`);
if (data) {
this.appendLine(Logger.data2String(data));
}
}
}
private now(): string {
const now = new Date();
return padLeft(now.getUTCHours() + '', 2, '0')
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
}
public updateConfiguration() {
this.trace = this.readTrace();
}
@@ -73,3 +81,7 @@ export class Logger {
return JSON.stringify(data, undefined, 2);
}
}
function padLeft(s: string, n: number, pad = ' ') {
return pad.repeat(Math.max(0, n - s.length)) + s;
}
@@ -234,6 +234,11 @@ export class MarkdownEngine {
const normalizeLink = md.normalizeLink;
md.normalizeLink = (link: string) => {
try {
// Normalize VS Code schemes to target the current version
if (isOfScheme(Schemes.vscode, link) || isOfScheme(Schemes['vscode-insiders'], link)) {
return normalizeLink(vscode.Uri.parse(link).with({ scheme: vscode.env.uriScheme }).toString());
}
// If original link doesn't look like a url with a scheme, assume it must be a link to a file in workspace
if (!/^[a-z\-]+:/i.test(link)) {
// Use a fake scheme for parsing
@@ -268,7 +273,11 @@ export class MarkdownEngine {
const validateLink = md.validateLink;
md.validateLink = (link: string) => {
// support file:// links
return validateLink(link) || isOfScheme(Schemes.file, link) || /^data:image\/.*?;/.test(link);
return validateLink(link)
|| isOfScheme(Schemes.file, link)
|| isOfScheme(Schemes.vscode, link)
|| isOfScheme(Schemes['vscode-insiders'], link)
|| /^data:image\/.*?;/.test(link);
};
}
@@ -10,7 +10,7 @@ const suite = 'Integration Markdown Tests';
const options: any = {
ui: 'tdd',
useColors: true,
useColors: (!process.env.BUILD_ARTIFACTSTAGINGDIRECTORY && process.platform !== 'win32'),
timeout: 60000
};
@@ -13,7 +13,7 @@ export const Schemes = {
data: 'data:',
vscode: 'vscode:',
'vscode-insiders': 'vscode-insiders:',
'vscode-resource': 'vscode-resource',
'vscode-resource': 'vscode-resource:',
};
const knownSchemes = [
@@ -4,33 +4,28 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { disposeAll } from '../util/dispose';
import { Disposable } from '../util/dispose';
import { isMarkdownFile } from './file';
export class MarkdownFileTopmostLineMonitor {
private readonly disposables: vscode.Disposable[] = [];
export class TopmostLineMonitor extends Disposable {
private readonly pendingUpdates = new Map<string, number>();
private readonly throttle = 50;
constructor() {
vscode.window.onDidChangeTextEditorVisibleRanges(event => {
super();
this._register(vscode.window.onDidChangeTextEditorVisibleRanges(event => {
if (isMarkdownFile(event.textEditor.document)) {
const line = getVisibleLine(event.textEditor);
if (typeof line === 'number') {
this.updateLine(event.textEditor.document.uri, line);
}
}
}, null, this.disposables);
}));
}
dispose() {
disposeAll(this.disposables);
}
private readonly _onDidChangeTopmostLineEmitter = new vscode.EventEmitter<{ resource: vscode.Uri, line: number }>();
public readonly onDidChangeTopmostLine = this._onDidChangeTopmostLineEmitter.event;
private readonly _onChanged = this._register(new vscode.EventEmitter<{ readonly resource: vscode.Uri, readonly line: number }>());
public readonly onDidChanged = this._onChanged.event;
private updateLine(
resource: vscode.Uri,
@@ -41,7 +36,7 @@ export class MarkdownFileTopmostLineMonitor {
// schedule update
setTimeout(() => {
if (this.pendingUpdates.has(key)) {
this._onDidChangeTopmostLineEmitter.fire({
this._onChanged.fire({
resource,
line: this.pendingUpdates.get(key) as number
});
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -138,6 +138,6 @@
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@types/node": "^10.14.8"
"@types/node": "^12.11.7"
}
}
@@ -35,7 +35,7 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict
public applyEdit(type: interfaces.CommitType, document: vscode.TextDocument, edit: { replace(range: vscode.Range, newText: string): void; }): void {
// Each conflict is a set of ranges as follows, note placements or newlines
// which may not in in spans
// which may not in spans
// [ Conflict Range -- (Entire content below)
// [ Current Header ]\n -- >>>>> Header
// [ Current Content ] -- (content)
@@ -75,4 +75,4 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict
private isNewlineOnly(text: string) {
return text === '\n' || text === '\r\n';
}
}
}
+4 -4
View File
@@ -2,10 +2,10 @@
# yarn lockfile v1
"@types/node@^10.14.8":
version "10.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.8.tgz#fe444203ecef1162348cd6deb76c62477b2cc6e9"
integrity sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw==
"@types/node@^12.11.7":
version "12.11.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
vscode-nls@^4.0.0:
version "4.0.0"
+1 -1
View File
@@ -457,7 +457,7 @@
"@types/glob": "^7.1.1",
"@types/js-yaml": "^3.12.1",
"@types/mocha": "^5.2.5",
"@types/node": "^11.9.3",
"@types/node": "^12.11.7",
"@types/request": "^2.48.1",
"@types/rimraf": "^2.0.2",
"@types/temp-write": "^3.3.0",
+4 -4
View File
@@ -161,10 +161,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.4.tgz#f83ec3c3e05b174b7241fadeb6688267fe5b22ca"
integrity sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ==
"@types/node@^11.9.3":
version "11.9.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.3.tgz#14adbb5ab8cd563f549fbae8dbe92e0b7d6e76cc"
integrity sha512-DMiqG51GwES/c4ScBY0u5bDlH44+oY8AeYHjY1SGCWidD7h08o1dfHue/TGK7REmif2KiJzaUskO+Q0eaeZ2fQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
"@types/request@^2.48.1":
version "2.48.1"
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "3.7.2"
"typescript": "3.7.3-insiders.20191123"
},
"scripts": {
"postinstall": "node ./postinstall"
+1 -1
View File
@@ -6,7 +6,7 @@
"git": {
"name": "MagicStack/MagicPython",
"repositoryUrl": "https://github.com/MagicStack/MagicPython",
"commitHash": "38422d302fe0b3e7716d26ce8cd7d0b9685f3a38"
"commitHash": "c0f8d514bbe6e9d3899f2b002bcd6971aef5e34b"
}
},
"license": "MIT",
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/MagicStack/MagicPython/commit/38422d302fe0b3e7716d26ce8cd7d0b9685f3a38",
"version": "https://github.com/MagicStack/MagicPython/commit/c0f8d514bbe6e9d3899f2b002bcd6971aef5e34b",
"name": "MagicPython",
"scopeName": "source.python",
"patterns": [
@@ -374,6 +374,7 @@
]
},
"member-access": {
"name": "meta.member.access.python",
"begin": "(\\.)\\s*(?!\\.)",
"end": "(?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",
"beginCaptures": {
@@ -1067,6 +1068,7 @@
}
},
"member-access-class": {
"name": "meta.member.access.python",
"begin": "(\\.)\\s*(?!\\.)",
"end": "(?<=\\S)(?=\\W)|$",
"beginCaptures": {
@@ -287,7 +287,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -298,7 +298,7 @@
},
{
"c": "request",
"t": "source.python",
"t": "source.python meta.member.access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -309,7 +309,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -320,7 +320,7 @@
},
{
"c": "META",
"t": "source.python constant.other.caps.python",
"t": "source.python meta.member.access.python constant.other.caps.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -331,7 +331,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -342,7 +342,7 @@
},
{
"c": "items",
"t": "source.python meta.function-call.python meta.function-call.generic.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.generic.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -353,7 +353,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -364,7 +364,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -408,7 +408,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -419,7 +419,7 @@
},
{
"c": "startswith",
"t": "source.python meta.function-call.python meta.function-call.generic.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.generic.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -430,7 +430,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -441,7 +441,7 @@
},
{
"c": "'",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.quoted.single.python punctuation.definition.string.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.quoted.single.python punctuation.definition.string.begin.python",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
@@ -452,7 +452,7 @@
},
{
"c": "HTTP_",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.quoted.single.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.quoted.single.python",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
@@ -463,7 +463,7 @@
},
{
"c": "'",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.quoted.single.python punctuation.definition.string.end.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.quoted.single.python punctuation.definition.string.end.python",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
@@ -474,7 +474,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -419,7 +419,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -430,7 +430,7 @@
},
{
"c": "size",
"t": "source.python",
"t": "source.python meta.member.access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -2223,7 +2223,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -2234,7 +2234,7 @@
},
{
"c": "next",
"t": "source.python meta.function-call.python meta.function-call.generic.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.generic.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -2245,7 +2245,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -2256,7 +2256,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4533,7 +4533,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4543,7 +4543,18 @@
}
},
{
"c": "fn ",
"c": "fn",
"t": "source.python meta.member.access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.python",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -4599,7 +4610,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4609,7 +4620,18 @@
}
},
{
"c": "memo ",
"c": "memo",
"t": "source.python meta.member.access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.python",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -4885,7 +4907,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4896,7 +4918,7 @@
},
{
"c": "memo",
"t": "source.python",
"t": "source.python meta.member.access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4940,7 +4962,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4951,7 +4973,7 @@
},
{
"c": "memo",
"t": "source.python meta.item-access.python",
"t": "source.python meta.member.access.python meta.item-access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4962,7 +4984,7 @@
},
{
"c": "[",
"t": "source.python meta.item-access.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.item-access.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4973,7 +4995,7 @@
},
{
"c": "args",
"t": "source.python meta.item-access.python meta.item-access.arguments.python",
"t": "source.python meta.member.access.python meta.item-access.python meta.item-access.arguments.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -4984,7 +5006,7 @@
},
{
"c": "]",
"t": "source.python meta.item-access.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.item-access.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5039,7 +5061,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5050,7 +5072,7 @@
},
{
"c": "fn",
"t": "source.python meta.function-call.python meta.function-call.generic.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.generic.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5061,7 +5083,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5072,7 +5094,7 @@
},
{
"c": "*",
"t": "source.python meta.function-call.python meta.function-call.arguments.python keyword.operator.unpacking.arguments.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python keyword.operator.unpacking.arguments.python",
"r": {
"dark_plus": "keyword.operator: #D4D4D4",
"light_plus": "keyword.operator: #000000",
@@ -5083,7 +5105,7 @@
},
{
"c": "args",
"t": "source.python meta.function-call.python meta.function-call.arguments.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5094,7 +5116,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5149,7 +5171,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5160,7 +5182,7 @@
},
{
"c": "memo",
"t": "source.python meta.item-access.python",
"t": "source.python meta.member.access.python meta.item-access.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5171,7 +5193,7 @@
},
{
"c": "[",
"t": "source.python meta.item-access.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.item-access.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5182,7 +5204,7 @@
},
{
"c": "args",
"t": "source.python meta.item-access.python meta.item-access.arguments.python",
"t": "source.python meta.member.access.python meta.item-access.python meta.item-access.arguments.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5193,7 +5215,7 @@
},
{
"c": "]",
"t": "source.python meta.item-access.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.item-access.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5237,7 +5259,7 @@
},
{
"c": ".",
"t": "source.python punctuation.separator.period.python",
"t": "source.python meta.member.access.python punctuation.separator.period.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5248,7 +5270,7 @@
},
{
"c": "search",
"t": "source.python meta.function-call.python meta.function-call.generic.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.generic.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5259,7 +5281,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python punctuation.definition.arguments.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.begin.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5270,7 +5292,7 @@
},
{
"c": "r",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python storage.type.string.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python storage.type.string.python",
"r": {
"dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF",
@@ -5281,7 +5303,7 @@
},
{
"c": "\"",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python punctuation.definition.string.begin.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python punctuation.definition.string.begin.python",
"r": {
"dark_plus": "string.regexp: #D16969",
"light_plus": "string.regexp: #811F3F",
@@ -5292,7 +5314,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp",
"r": {
"dark_plus": "support.other.parenthesis.regexp: #CE9178",
"light_plus": "support.other.parenthesis.regexp: #D16969",
@@ -5303,7 +5325,7 @@
},
{
"c": "[",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp",
"r": {
"dark_plus": "punctuation.character.set.begin.regexp: #CE9178",
"light_plus": "punctuation.character.set.begin.regexp: #D16969",
@@ -5314,7 +5336,7 @@
},
{
"c": "0-9-",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp",
"r": {
"dark_plus": "constant.character.set.regexp: #D16969",
"light_plus": "constant.character.set.regexp: #811F3F",
@@ -5325,7 +5347,7 @@
},
{
"c": "]",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp",
"r": {
"dark_plus": "punctuation.character.set.end.regexp: #CE9178",
"light_plus": "punctuation.character.set.end.regexp: #D16969",
@@ -5336,7 +5358,7 @@
},
{
"c": "*",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"r": {
"dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D",
"light_plus": "keyword.operator.quantifier.regexp: #000000",
@@ -5347,7 +5369,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp",
"r": {
"dark_plus": "support.other.parenthesis.regexp: #CE9178",
"light_plus": "support.other.parenthesis.regexp: #D16969",
@@ -5358,7 +5380,7 @@
},
{
"c": "\\s",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.escape.special.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.escape.special.regexp",
"r": {
"dark_plus": "string.regexp: #D16969",
"light_plus": "string.regexp: #811F3F",
@@ -5369,7 +5391,7 @@
},
{
"c": "*",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"r": {
"dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D",
"light_plus": "keyword.operator.quantifier.regexp: #000000",
@@ -5380,7 +5402,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp",
"r": {
"dark_plus": "support.other.parenthesis.regexp: #CE9178",
"light_plus": "support.other.parenthesis.regexp: #D16969",
@@ -5391,7 +5413,7 @@
},
{
"c": "[",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp",
"r": {
"dark_plus": "punctuation.character.set.begin.regexp: #CE9178",
"light_plus": "punctuation.character.set.begin.regexp: #D16969",
@@ -5402,7 +5424,7 @@
},
{
"c": "A-Za-z",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp",
"r": {
"dark_plus": "constant.character.set.regexp: #D16969",
"light_plus": "constant.character.set.regexp: #811F3F",
@@ -5413,7 +5435,7 @@
},
{
"c": "]",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp",
"r": {
"dark_plus": "punctuation.character.set.end.regexp: #CE9178",
"light_plus": "punctuation.character.set.end.regexp: #D16969",
@@ -5424,7 +5446,7 @@
},
{
"c": "+",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"r": {
"dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D",
"light_plus": "keyword.operator.quantifier.regexp: #000000",
@@ -5435,7 +5457,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp",
"r": {
"dark_plus": "support.other.parenthesis.regexp: #CE9178",
"light_plus": "support.other.parenthesis.regexp: #D16969",
@@ -5446,7 +5468,7 @@
},
{
"c": ",",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python",
"r": {
"dark_plus": "string.regexp: #D16969",
"light_plus": "string.regexp: #811F3F",
@@ -5457,7 +5479,7 @@
},
{
"c": "\\s",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.escape.special.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.escape.special.regexp",
"r": {
"dark_plus": "string.regexp: #D16969",
"light_plus": "string.regexp: #811F3F",
@@ -5468,7 +5490,7 @@
},
{
"c": "+",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"r": {
"dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D",
"light_plus": "keyword.operator.quantifier.regexp: #000000",
@@ -5479,7 +5501,7 @@
},
{
"c": "(",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp",
"r": {
"dark_plus": "support.other.parenthesis.regexp: #CE9178",
"light_plus": "support.other.parenthesis.regexp: #D16969",
@@ -5490,7 +5512,7 @@
},
{
"c": ".",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.match.any.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.match.any.regexp",
"r": {
"dark_plus": "string.regexp: #D16969",
"light_plus": "string.regexp: #811F3F",
@@ -5501,7 +5523,7 @@
},
{
"c": "*",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp",
"r": {
"dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D",
"light_plus": "keyword.operator.quantifier.regexp: #000000",
@@ -5512,7 +5534,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp",
"r": {
"dark_plus": "support.other.parenthesis.regexp: #CE9178",
"light_plus": "support.other.parenthesis.regexp: #D16969",
@@ -5523,7 +5545,7 @@
},
{
"c": "\"",
"t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python punctuation.definition.string.end.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python punctuation.definition.string.end.python",
"r": {
"dark_plus": "string.regexp: #D16969",
"light_plus": "string.regexp: #811F3F",
@@ -5534,7 +5556,7 @@
},
{
"c": ",",
"t": "source.python meta.function-call.python meta.function-call.arguments.python punctuation.separator.arguments.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python punctuation.separator.arguments.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5545,7 +5567,7 @@
},
{
"c": " i",
"t": "source.python meta.function-call.python meta.function-call.arguments.python",
"t": "source.python meta.member.access.python meta.function-call.python meta.function-call.arguments.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -5556,7 +5578,7 @@
},
{
"c": ")",
"t": "source.python meta.function-call.python punctuation.definition.arguments.end.python",
"t": "source.python meta.member.access.python meta.function-call.python punctuation.definition.arguments.end.python",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
+1 -1
View File
@@ -356,7 +356,7 @@
"dependencies": {
"linux-release-info": "^2.0.0",
"promisify-child-process": "^3.1.1",
"sudo-prompt": "^9.0.0",
"sudo-prompt": "9.1.1",
"vscode-nls": "^4.0.0",
"yamljs": "^0.3.0"
},
@@ -182,7 +182,7 @@ export class PlatformService implements IPlatformService {
}
}
private sudoExec(command: string, options: sudo.SudoOptions): Promise<CommandOutput> {
private sudoExec(command: string, options: { [key: string]: any }): Promise<CommandOutput> {
return new Promise<CommandOutput>((resolve, reject) => {
sudo.exec(command, options, (error, stdout, stderr) => {
if (error) {
-1
View File
@@ -6,5 +6,4 @@
/// <reference path='../../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../../src/sql/azdata.d.ts'/>
/// <reference path='../../../../src/sql/azdata.proposed.d.ts'/>
/// <reference path='../../../../src/typings/sudo-prompt.d.ts'/>
/// <reference types='@types/node'/>
+4 -4
View File
@@ -643,10 +643,10 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
sudo-prompt@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.0.0.tgz#eebedeee9fcd6f661324e6bb46335e3288e8dc8a"
integrity sha512-kUn5fiOk0nhY2oKD9onIkcNCE4Zt85WTsvOfSmqCplmlEvXCcPOmp1npH5YWuf8Bmyy9wLWkIxx+D+8cThBORQ==
sudo-prompt@9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.1.1.tgz#73853d729770392caec029e2470db9c221754db0"
integrity sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==
supports-color@4.4.0:
version "4.4.0"
+1 -1
View File
@@ -64,7 +64,7 @@
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^10.14.8",
"@types/node": "^12.11.7",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
+4 -4
View File
@@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.6.tgz#b8622d50557dd155e9f2f634b7d68fd38de5e94b"
integrity sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==
"@types/node@^10.14.8":
version "10.14.17"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.17.tgz#b96d4dd3e427382482848948041d3754d40fd5ce"
integrity sha512-p/sGgiPaathCfOtqu2fx5Mu1bcjuP8ALFg4xpGgNkcin7LwRyzUKniEHBKdcE1RPsenq5JVPIpMTJSygLboygQ==
"@types/node@^12.11.7":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
ajv@^6.5.5:
version "6.10.0"
+3
View File
@@ -0,0 +1,3 @@
# Language Features for Search Result files
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const withDefaults = require('../shared.webpack.config');
module.exports = withDefaults({
context: __dirname,
resolve: {
mainFields: ['module', 'main']
},
entry: {
extension: './src/extension.ts',
}
});
+64
View File
@@ -0,0 +1,64 @@
{
"name": "search-result",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
"publisher": "vscode",
"license": "MIT",
"engines": {
"vscode": "^1.39.0"
},
"categories": [
"Programming Languages"
],
"main": "./out/extension.js",
"activationEvents": [
"*"
],
"scripts": {
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:search-result ./tsconfig.json"
},
"contributes": {
"commands": [
{
"command": "searchResult.rerunSearch",
"title": "%searchResult.rerunSearch.title%",
"category": "Search Result",
"icon": {
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
}
],
"menus": {
"editor/title": [
{
"command": "searchResult.rerunSearch",
"when": "editorLangId == search-result",
"group": "navigation"
}
]
},
"languages": [
{
"id": "search-result",
"extensions": [
".code-search"
],
"aliases": [
"Search Result"
]
}
],
"grammars": [
{
"language": "search-result",
"scopeName": "text.searchResult",
"path": "./syntaxes/searchResult.tmLanguage.json"
}
]
},
"devDependencies": {
"vscode": "^1.1.36"
}
}
@@ -0,0 +1,5 @@
{
"displayName": "Search Result",
"description": "Provides syntax highlighting and language features for tabbed search results.",
"searchResult.rerunSearch.title": "Search Again"
}

Some files were not shown because too many files have changed in this diff Show More